Как стать автором
Обновить

Комментарии 41

Для таких вещей надо ввести кеширование предыдущего результата на серверной стороне и отдавать предыдущий пока не накопился новый. Как только готов новый объект/массив — кешировать его. И всё. Тогда мгновенно можно будет показать результат вычислений.
Путь 2 — пусть себе висит запрос пока не сгенерируется ответ. По окончании всё равно результат приедет в функцию success. Однако при этом пользователь ближайшие 10-20 секунд (время генерации) будет сидеть без данных.
Надо внести немного ясности:
1. В процессе написания одного скрипта обнаружил, что нельзя немедленно использовать ответ ajax запроса
2. В моём случае запрос передается серверному скрипту, который… наполняет json файл. Наполнение… от 12 до 20 секунд...

Ответ как раз можно использовать можно сразу (после получения его от сервера), только ждать этого ответа приходиться долго. Так?

Ну и совсем глобальную переменную можно не заводить, а использовать локальную в области видимости соответсвующей.

А так я пожалуй прочту еще раз, как-то непонятно все=), таймер еще 20 секундный… это точно можно сделать проще=)
Если совсем буквально, то конечно ждать приходиться долго, именно поэтому пришлось извратиться.
Локальная в области видимости соответствующей — с этим пока не знаком. Где то слышал что с функцией ajax setInterval setTimeout по другому как то принято, но получилось пока так.
А почему вы просто сначала не используете старые данные ( а зачем-то вызываете полу-рыбный аякс-запрос, и только после его завершения начинаете использовать), в то же время посылая запрос на получения новых данных сразу к 'curences.json' (Как данные наполнятся, так сразу и отработает success)?

По сути запрос к proxy.php никому не нужен, я думаю нет проблемы наполнять curences.json по обращению к нему напрямую, а не через proxy.php
На сколько я понял, ajax используется просто для того что бы продернуть обновление курсов (что логичнее наверное было бы сделать кроном… но, видимо, на то есть причины). А чтобы запрос не мешал пользователю — его вынесли в ajax, что бы пользователь не ждал. Если вдруг накапитанил — извиняйте.

Но финта с таймером я, честно говоря, не понял.
Дело в том что если без таймера считать json, то тот самый первый пользователь, который как Вы выразились продёрнет обновление курсов, увидит старые данные (данные обновляются до 20сек).
Что-то я запутался.
Вы посылаете ajax запрос к скрипту proxy.php, который в свою очередь обращается к чему-то еще на другом домене. Так? При этом скрипт proxy.php отрабатывает за ~20 сек? Т.е. после отправки первого запроса ajax соединение не разрывается?
Ну как то так
Тогда минимум от таймера можно было избавиться. Для этого достаточно чтобы proxy.php отдавал json с курсами.
надо потестить
Тут финт в том, что proxy.php не отдает json. За джейсоном посылают второй запрос через 20 секунд, proxy.php просто запускает или не запускает обновление джейсон-файла.

Я собственно, и говорю о том, что два запроса – это излишне=)
Сегодня уже не могу, завтра проверю, была бы карма, сказал бы спасибо.
proxy.php наполняет при помощи api цбрф актуальными данными файл curences.json, наполнение происходит с приходом первого посетителя в определённые 24 часа, а в остальное время, Вы совершенно правы используются старые данные. Про полурыбнй вопрос не понял.
Почему нельзя наполнять curences.json при обращении напрямую к нему (ну или ненаполнять, если данные свежие, а просто отдать, этот момент сейчас не так важен=)? Зачем идти сначала к proxy.php?
Потому что есть политика безопасности браузеров, напрямую наполнять данными с другого сервера можно только с jsonp. В моём случае дополнительно используется php класс для общения с цбрф, так что по другому никак.
Не, не у вас там два запроса c юрлами:
url: «proxy.php»,
url: 'curences.json',

Работает так: по запросу к proxy.php наполняется curences.json, далее делаем запрос к curences.json и забираем результат.
Вопрос: почему нельзя обратся сразу к curences.json, и если там данные старые, то сервер пойдет к апи и наполнит файл новыми, в этом время запрос просто будет висеть.

Так вот, так можно сделать и нужно, в таком случае, вам не нужен таймер, и первый аякс запрос (то, что вы выполняете по его завершению, надо выполнять сразу).
Потому что решение старые новые или старые основывается на серверном времени, а не клиентском. У клиента время может на год назад стоять, да и часовые пояса.
Опять мимо=)

Суть моего предложения, в том, чтобы у вас был один юрл, пусть это будет curences.php
Алгоритм:
1. Считаем со старыми данными из глобальной переменной (вместо первого аякс-запроса, где мы испольузем старые данные из глобальной переменной только после ответа сервера, используем их сразу)
2. Сразу кидаем запрос на curences.php
тут два варианта
2.1 Сервер сегодня данные не обновлял, тогда он идет к апи, запрос висит сколько надо, по success мы получаем обновленные данные
2.2 Сервер уже сходил сегодня за данными и сохранил их в файл, пусть это будет curences.json
тогда скрипт, просто отдает этот файл и все

Никакого таймера, с магическими 20 секундами
curences.php это некая смесь proxy.php и curences.json
В нем есть логика из proxy.php по обновлению новых данных или не обновлению, но в отличие от proxy.php он отдает результат нам нужный и нам не надо делать еще один запрос уже на curences.json
Для ясности наверное приведу proxy.php
<?php
$filename = "curences.json";
if (is_readable($filename)) {
$fd = fopen($filename, "r") or die("Can't open file!");
$fstring = fread($fd, filesize($filename));
$fjson = json_decode($fstring);
fclose($fd);
}

$date = date('Y-m-d', time()-86400);

if ($fjson -> data != $date) {
require_once("ClassExchangeRatesCBRF.php");
$rates = new ExchangeRatesCBRF($date);
$array = array();
$array["data"] = $date;
$array["USD"] = $rates->GetRate("USD");
$array["EUR"] = $rates->GetRate("EUR");
$array["UAH"] = $rates->GetRate("UAH");
$json = json_encode($array);

//Если файл существует и в него возможна запись
if ($array["USD"]>0) {
if (is_writeable($filename) ) {
// Открыть файл и установить указатель текущей позиции в начало файла
$fd = fopen($filename, 'w');
// Записать содержимое $data в файл
fwrite($fd, $json);
// Закрыть файл
fclose($fd);
}
}
}
?>
Надо добавить, чтобы оно возвращало котировки, либо сразу из файла, если он свежий, либо после обновления их возвращало, а не просто записывало в файл и закрывало его.
Вполне вероятно, я привел данный пример чтобы показать что можно использовать ответ ajax функции в любом месте скрипта, а также можно обойтись без крон. В настоящее время я пишу ещё один скриптик, который будет использовать котировки 35ти валют за последний год, всё будет загоняться в субд, и наверное всё таки привяжу к крон. Старый proxy.php будет переделан уже под работу с субд.
Ну то, что данные можно передать куда хочешь это вполне логично=)

Насчет крона, тут proxy.php тоже не обязателен, вы при обращении к странице можете проверять свежесть данных, отдать страницу и спокойно обновлять данные если надо.

Свежесть данных тоже надо бы более быстрыми методами проверять, чем читать весь файл, раскодировать джейсон и выдирать оттуда дату, хотя бы по времени создания/модификации файла, либо же давать имена этим файлам в виде YYYY-MM-DD.json и проверять просто наличие такого файла, тут главное старые не забывать удалять.
Варианта 3:
1. Сервер не ходил
2. Сервер ходит
3. Сервере сходил

Второй самый интересный. То есть один клиент уже послал сервер в цб, а второму курс нужен. По-хорошему он должен узнать, что первый скрипт уже пошёл, подождать пока он сходит, а потом взять у него готовые данные. Это ещё цветочки, самое интересно когда первый завис или молча умер.
Нужно сразу вставлять в страницу текущие данные и время создания файла и текущее серверное время. Если последняя дата записи в файл вчерашняя, то надо выполнить прокси.пхп, причём делать это надо не в аяксе, зачем перекладывать на юзера то, чем должен заниматься сервак? Если вчерашний день, то запуск скрипта прокси.пхп, причём запуск лучше сделать. Если текущий день серверной даты больше чем день даты данных, то вот тут через минуту улетает аякс на обновление.
Всё что Вы написали сделано в proxy.pxp
Вы случайно не проектировали русские машины, до того как заняться программированием?
Нет, гораздо смешнее то, что не срабатывает таймер если так написать:
success: setTimeout(function(){ curencesjson()}, 20000);
правда?
Он не будет срабатывать, так как success это должна быть функция, а вы ему объект таймера даете.
Так заработает:
success: function(){setTimeout(curencesjson, 20000);}
Но смысла в таком 0
Извините, чуть неправильно написал, имелось в виду как раз через функцию. Не работает проверено.
Ну то что я написал работает так:
по success вызывается анонимная функция,
в которой создается таймаут на 20с, после чего выполняется функция curencesjson
Это точно работает=)

Другое дело, что сейчас данные в неё никак не передаются, но это тоже не беда, так передадутся:
success: function(data){
  setTimeout(function(){
    curencesjson(data)
  }, 20000);
}
Протестировали? Дело пройденное, поверьте я пытался варьировать.
А чего тут тестировать=)

http://jsfiddle.net/ctjng/

Я уменьшил время, а роль curencesjson выполняет myFunc показывающая алерт.
http://jsfiddle.net/ctjng/2/

Сверху старая версия, кто ж знал, что ссылка меняется=)
function myFunc(){
alert('Hello!');
}
$(function(){
$.ajax({
success: function(){
setTimeout(function(){
myFunc();
},5000);
}
});
})();

Пока Вы писали новую я доделал старую ))
Но у меня тогда отдавало не обновленный json, может дело было в том что таймером опять вызывался ajax? Пора заканчивать, я тут уже до отрицательного рейтинга написался.
Да трололо, если код в продакшене такой же, то при старте запроса, сначала вызовется запрос к вчерашнему файлу, потом стартанет таймер, а потом вызовется запрос к proxy.php.
А по теме — бессмысленный бред.
Ёханый бабай. О чем мы сейчас говорим? Тред на 40 комментариев на тему не просто велосипеда, а колеса к нему. Господа, ИМХО тут не школа новичков программирования и эта тема — пустая совершенно. Я с радостью расскажу в личку многоуважаемому Lanrete как бы сделал эту задачу я при условии: а) просьбы; б) более полной исходной картины — имеющиеся ресурсы, возможность использования мемкеша, БД, файлов и т.д.
Но это не тема для топика.
Тема ни о чем и огрызки кода ниочем. Вы бы сначало суть задачи расскази и требования к ней. В частности может он там что-то покупает, а цены старые 20 секунд висят. Задача простая, решений может быть много, так что данное описание не могу считать нормальной постановкой и решением задачи.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории