Как опросить 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
    });
}

Это имеет следующие преимущества:

  1. Не создается ненужного обещания, чтобы попытаться окружить вызов ajax, который уже имеет обещание. Это позволяет избежать одного из общих шаблонов обещаний.
  2. Последующие вызовы API просто связывают исходное обещание.
  3. Там нет необходимости использовать $.when() когда у тебя просто одно обещание. Вы можете просто использовать .then() прямо на это.
  4. Все ошибки автоматически возвращаются к первоначальному обещанию.
  5. Это использует стандарт ES6 .then() (что на самом деле становится более законно стандартным в jQuery 3.x - хотя он работает в jQuery 1.x и 2.x со своими нестандартными причудами), что делает эту логику более совместимой с другими производящими обещание асинхронными функциями.

Кроме того, здесь есть ряд других идей повторных попыток: шаблоны проектирования Promise Retry

Другие вопросы по тегам