2

我以循环方式从多个来源异步轮询数据,并希望在所有这些轮询完成后重复轮询。我正在尝试将 jQuery Deferred 对象与“always”一起使用来重复我的轮询,如下面的代码所示:

function makeAjaxCall(region) {
    var params = {
        'action': POLLER.action,
        },
        url = POLLER.region_to_url[region];

    return $.ajax({
        dataType: "json",
        url: url,
        data: params,
        success: (function(region) {
                      return function(result, status) { 
                          handleAjaxResult(result, status, region); 
                      };
                 })(region),
        error: (function(region) {
                    return function(jqXHR, textStatus, errorThrown) { 
                        handleAjaxError(jqXHR, textStatus, errorThrown, region); 
                    };
                })(region)
    });
}

function nextPoll() {
    if(!polling) {
        return;
    }

    var requests = [];

    $.each(POLLER.regions, function(i, region) {
        requests.push(makeAjaxCall(region));
    });

    $.when.apply($, requests)
        .always(function() {
            log("deferred.always ", this)
            updateSummary();
            var delay = POLLER.POLLER_INTERVAL_MS;
            if (delay != 0) {
                pollerTimeout = setTimeout(nextPoll, delay);
            }
        }).fail(function() {
            log("fail for ",this)
        });
}

我的问题是,当我的一项民意调查失败时,会调用“始终”块。我可能错误地假设在所有请求完成或失败后应该调用“总是” 。我打算让它以这种方式运行,所以任何关于不同的,也许更简单的方法的提示都会很棒。

4

2 回答 2

0

感谢@Ross 的帮助。我设法重新编写代码以删除对 Deferred 对象的使用,并只跟踪返回了多少 ajax 请求,因此在 ajax 调用的成功和错误处理程序中,我也总是调用相同的函数来跟踪轮询次数.

function makeAjaxCall(region) {
    var params = {
        'action': POLLER.action,
        },
        url = POLLER.region_to_url[region];

    $.extend(params, POLLER.filters);

    return $.ajax({
        dataType: "json",
        url: url,
        data: params,
        success: (function(region) {
            return function(result, status) { handleAjaxResult(result, status, region); };
        })(region),
        error: (function(region) {
            return function(jqXHR, textStatus, errorThrown) { handleAjaxError(jqXHR, textStatus, errorThrown, region); };
        })(region)
    });
}

function handleAjaxResult(result, status, region) {
    POLLER.data[region] = results.data;
    afterAjaxResult();
}

function handleAjaxError(jqXHR, textStatus, errorThrown, region) {
    POLLER.ajax_errors[region].count++;
    afterAjaxResult();
}

function nextPoll() {
    if(!polling) {
        return;
    }

    POLLER.round_robin = 0;

    $.each(POLLER.regions, function(i, region) {
        makeAjaxCall(region)
    });
}

function afterAjaxResult() {
    POLLER.round_robin++;
    if(POLLER.regions.length === POLLER.round_robin) {
        updateSummary();
        var delay = POLLER.POLLER_INTERVAL_MS;
        if (delay != 0) {
            pollerTimeout = setTimeout(nextPoll, delay);
        }
    }
}

有关示例,请参见此 jsFiddle

于 2013-09-03T13:48:05.997 回答
0

我为此写了一个扩展$.when

此扩展将所有成功和失败视为进度事件。在所有的 Promise 都完成后,如果没有错误,全局 Promise 就会被解决。否则,全局承诺将被拒绝。

$.whenAll- https://gist.github.com/4341799测试

示例用法:

$.whenAll($.getJSON('foo'), $.getJSON('bar'))
  .then(
    doneCallback
    ,failcallback
    // progress callback
    // the only problem is $.ajax.done/fail states call their callbacks 
    // with params in different locations (except for state)
    ,function(data, state, jqXhr) {
      if (state == 'success') {
        // do happy stuff
      }
      else { // error (fail)
        // `data` is actually the jqXhr object for failed requests
        // `jqXhr` is the text of the error "Not Found" in this example
      }
    }
  )
;
于 2014-11-24T08:58:08.723 回答