Как опросить API как часть $.Deferred()
Приведенный ниже нефункциональный пример должен объяснить, что я пытаюсь сделать, я просто не понимаю шаблон, который мне нужно использовать для достижения этой цели. Я попытался поискать в Google, чтобы понять опрос и отложить, но я не мог найти ничего, что мог понять.
У меня есть функция, которая опрашивает API, и я хочу подождать, пока этот опрос вернет ожидаемый результат (ожидание, пока конечная точка покажет, что что-то изменилось), прежде чем продолжить работу с моей основной функцией. Что я делаю неправильно?
Редактировать: я должен добавить, что то, что кажется неправильным с кодом ниже, это то, что хотя deferred.resolve()
в конце концов вызывается, кажется, это не то же самое deferred
что вернули, поэтому when
никогда не активируется в main()
, Я предполагаю, что это связано с тайм-аутом, то есть deferred
одеться при первом повторе. Во всяком случае, это мое предположение.
function pollAPI() {
var deferred = $.Deferred();
$.ajax({
url: url,
contentType: 'application/JSON',
method: 'GET'
}).done(function(data){
if (!desiredResult) {
setTimeout(function() {
pollAPI();
}, 1000);
} else {
deferred.resolve();
}
}).error(deferred.reject());
return deferred.promise();
}
function main() {
$.when(pollAPI()).then(function() {
// do something now that the API has returned the expected result
});
1 ответ
Вы можете использовать цепочку последующих звонков на pollAPI()
функция для создания единого обещания, к которому прикованы другие. Это будет работать так:
// utility function to create a promise that is resolved after a delay
$.promiseDelay = function(t) {
return $.Deferred(function(def) {
setTimeout(def.resolve, t);
}).promise();
}
function pollAPI() {
return $.ajax({
url: url,
contentType: 'application/JSON',
method: 'GET'
}).then(function(data) {
// some logic here to test if we have desired result
if (!desiredResult) {
// chain the next promise onto it after a delay
return $.promiseDelay(1000).then(pollAPI);
} else {
// return resolved value
return someValue;
}
});
}
function main() {
pollAPI().then(function(result) {
// got desired result here
}, function(err) {
// ended with an error here
});
}
Это имеет следующие преимущества:
- Не создается ненужного обещания, чтобы попытаться окружить вызов ajax, который уже имеет обещание. Это позволяет избежать одного из общих шаблонов обещаний.
- Последующие вызовы API просто связывают исходное обещание.
- Там нет необходимости использовать
$.when()
когда у тебя просто одно обещание. Вы можете просто использовать.then()
прямо на это. - Все ошибки автоматически возвращаются к первоначальному обещанию.
- Это использует стандарт ES6
.then()
(что на самом деле становится более законно стандартным в jQuery 3.x - хотя он работает в jQuery 1.x и 2.x со своими нестандартными причудами), что делает эту логику более совместимой с другими производящими обещание асинхронными функциями.
Кроме того, здесь есть ряд других идей повторных попыток: шаблоны проектирования Promise Retry