#javascript #jquery
#javascript #jquery
Вопрос:
ОБНОВЛЕНИЕ Следуя предложению @ Ryan Olds включить setTimeout в обратный вызов, я должен уточнить, что в моем производственном коде я вызываю несколько URL-адресов для получения данных json с нескольких сайтов. (Обновил код JavaScript ниже).
Возможно ли иметь только несколько таймаутов, разбросанных по всей этой функции?
У меня есть самозапускающаяся функция updateFunction следующим образом:
(function update() {
$.ajax({
type: 'GET',
url: "http://myexample.com/jsondata",
dataType: 'json',
success: function (data) {
// do some callback stuff
},
async: false
});
$.ajax({
type: 'GET',
url: "http://myexample2.com/jsondata2",
dataType: 'json',
success: function (data) {
// do some further callback stuff
},
async: false
});
setTimeout(update, 2000);
})();
Чего я ожидал от этого кода
Я надеялся, что эта функция перейдет к целевому URL и дождется результата, а затем выполнит успешный обратный вызов. Тогда (и только тогда) не удастся установить 2-секундный тайм-аут для повторного вызова функции.
Что, похоже, происходит вместо
Вместо этого выполняется код запроса GET, и до обработки ответа уже установлен тайм-аут.
Чего мне не хватает? Как я могу сделать это полностью синхронным?
Комментарии:
1. Вы могли бы поместить setTimeout внутри успешного обратного вызова для вызова AJAX, это одно из предложений. Вы также могли бы использовать setInterval вместо setTimeout и вызывать его после основного объявления.
Ответ №1:
На вашем месте я бы воспользовался поддержкой jQuery для отложенных действий.
(function update() {
$.when($.ajax({
type: 'GET',
url: "http://myexample.com/jsondata",
dataType: 'json',
success: function (data) {
// do some callback stuff
}
}), $.ajax({
type: 'GET',
url: "http://myexample2.com/jsondata2",
dataType: 'json',
success: function (data) {
// do some further callback stuff
}
}), $.ajax({
// more requests as you like
})).then(function() {
// when all the requests are complete
setTimeout(update, 2000);
});
}());
Гораздо приятнее, ИМХО, чем возиться с синхронными запросами. Действительно, если запросы являются междоменными, это практически ваш единственный вариант.
Смотрите
Ответ №2:
Перенесите время ожидания на обратный вызов с успехом. Запрос синхронен, казалось бы, обратный вызов — нет.
Комментарии:
1. @Ryan — просто обновил мой вопрос, поскольку на самом деле он недостаточно прояснил. Возможно ли иметь только несколько таймаутов, разбросанных по всей этой функции?
2. Должны ли запросы выполняться в определенной последовательности?
3. В идеале они бы это сделали, хотя на практике не было бы проблемой, если бы все они возвращались в разное время — при условии, что цикл не повторяется, пока все они не вернутся
4. Нет, я не думаю, что запросы синхронны. Это междоменные запросы, что означает, что jQuery собирается использовать JSONP, и это всегда асинхронно.
5. Вам нужно будет реализовать счетчик в update (), который увеличивается и проверяется при каждом из обратных вызовов. Только после завершения обоих обратных вызовов вызывается следующий setTimeout. Если вы этого не сделаете, вы создадите условие гонки.
Ответ №3:
Я бы изменил настройку следующим образом:
function update() {
$.ajax({
type: 'GET',
url: "http://myexample.com/jsondata",
dataType: 'json',
success: function (data) {
// do some callback stuff
},
async: false
});
$.ajax({
type: 'GET',
url: "http://myexample2.com/jsondata2",
dataType: 'json',
success: function (data) {
// do some further callback stuff
},
async: false
});
}
setInterval(update, 2000);
update(); // only necessary if you can't wait 2 seconds before 1st load.
Комментарии:
1. Мне нужно было бы проверить, но я не знаю, приостанавливается ли setInterval / setTimeout во время синхронных запросов. Что, если запросы занимают больше 2 секунд? Вы вызываете отставание.
Ответ №4:
Вы не можете сделать это полностью синхронным, потому что вы настраиваете вызовы в альтернативные домены. Это делается (внутри jQuery) путем создания <script>
тегов и добавления их в документ. Браузеры выполняют эти вызовы асинхронно, и все. Вы не можете отправлять обычные xhr-запросы к доменам, отличным от вашего собственного.
Я не могу представить, почему вы хотите, чтобы что-то подобное было синхронным, тем более что вы выполняете многие из этих операций.
Комментарии:
1. Просто для пояснения, как упоминалось @Ryan Olds — не было бы проблемой, если бы все они возвращались в разное время — при условии, что цикл не повторяется, пока все они не вернутся. Я подумал, что сделать запросы синхронными было бы лучшим способом продвижения вперед на основе этого требования.
2. @beardtwizzle сейчас есть лучшие способы сделать это, как описывает @lonesomeday в своем ответе 🙂
Ответ №5:
Я не думаю, что async: false
работает с междоменными запросами.
Из документации: async Boolean По умолчанию: true По умолчанию все запросы отправляются асинхронно (т. Е. по умолчанию установлено значение true). Если вам нужны синхронные запросы, установите для этого параметра значение false. Междоменные запросы и запросы типа данных «jsonp» не поддерживают синхронную работу. Обратите внимание, что синхронные запросы могут временно блокировать браузер, отключая любые действия, пока запрос активен.
В любом случае, возможно, вы можете установить некоторые условия для запуска запросов в нужном вам порядке.