如何将API作为$ .Deferred()的一部分进行轮询

时间:2016-09-15 01:25:59

标签: javascript jquery promise jquery-deferred

下面的非功能性示例应该解释我尝试做什么,我只是不理解我需要用来完成它的模式。我试着谷歌搜索了解民意并推迟,但我找不到任何我能理解的东西。

我有一个轮询API的函数,我想在继续我的main函数之前等待该轮询返回预期结果(等待端点指示某些内容已经改变)。我做错了什么?

编辑:我应该补充说下面代码出错的地方是即使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 个答案:

答案 0 :(得分:3)

您可以使用对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调用。这避免了其中一个common promise anti-patterns
  2. 对API的后续调用只是链接到原来的承诺。
  3. 当您只有一个承诺时,无需使用$.when()。您可以直接在其上使用.then()
  4. 所有错误都会自动渗透回原来的承诺。
  5. 这使用了ES6标准.then()(实际上它在jQuery 3.x中变得更加合法 - 虽然它适用于jQuery 1.x和2.x以及它自己的非标准怪癖)逻辑与其他产生许可的异步函数更兼容。
  6. 此外,还有其他一些重试方法:Promise Retry Design Patterns