承诺和经常性的AJAX调用

时间:2014-03-19 10:58:53

标签: javascript jquery ajax promise

我正在尝试提出一个签名与jQuery.ajax相同的函数。它是一个单独的函数,因为根据响应中的HTTP状态,它应该完成并解析返回的promise,或者发出具有相同参数的延迟后续AJAX请求(因此重现)。虽然我有一个有效的解决方案,但我觉得它是一个承诺反模式,因为我明确地调用$.Deferred()来表示进程的状态。问题:

  • 是否可以重复使用$.ajax调用返回的“可用”对象,如同后续调用返回的承诺一样?
  • 每次调用另一个progress时,您如何在承诺链上加入$.ajax调用?

请参阅我的功能:

callAPI = function(jqAjaxOptions, deferred) {
  if (deferred == null) {
    deferred = $.Deferred();
  }
  $.ajax(jqAjaxOptions).always(function(data, status, xhr) {
    var args;
    args = _.toArray(arguments);
    switch (xhr.status) {
      case 200:
        return deferred.resolve.apply(deferred, args);
      case 201:
      case 202:
        return setTimeout(function() {
          return callAPI(jqAjaxOptions, deferred);
        }, 2000);
      default:
        deferred.reject.apply(deferred, args);
        if (data.responseText) {
          return app.notifier.set(JSON.parse(data.responseText));
        } else {
          return app.notifier.set({
            title: "Couldn't contact data server.",
            content: "It seems the API server is down. Please contact the DAV team."
          });
        }
    }
  });
  return deferred.promise();
};

1 个答案:

答案 0 :(得分:1)

  

是否可以重用$ .ajax调用返回的“thenable”对象,就像链接后续调用返回的promise一样?

是和否。您将丢失多个参数,并且无法发出进度事件。它看起来像这样:

function timeout(ms) {
    var d = $.Deferred();
    setTimeout(d.resolve, ms);
    return d.promise();
}
function callApi(ajaxOptions) {
    function tryit () {
        return $.ajax(ajaxOptions).then(data) {
             if (this.status == 200)
                 return data;
             else if (this.status == 201 || this.status == 202)
                 return timeout(2000).then(tryit);
             else
                 return $.Deferred().reject(this.responseText
                   ? JSON.parse(this.responseText)
                   : {
                     title: "Couldn't contact data server.",
                     content: "It seems the API server is down. Please contact the DAV team."
                 });
        });
    }
    return tryit();
}
  

每次调用另一个$ .ajax时,你如何在promise链上加入进度调用?

只需致电notify

function callApi(ajaxOptions) {
    var deferred = $.Deferred();
    function tryit() {
        $.ajax(jqAjaxOptions).always(function() {
            switch (this.status) {
                case 200:
                    return deferred.resolveWith(this, arguments);
                case 201:
                case 202:
                    deferred.notify("Next try in 2s");
                    return setTimeout(tryit, 2000);
                default:
                    deferred.notify(this.responseText
                      ? JSON.parse(this.responseText);
                      : {
                            title: "Couldn't contact data server.",
                            content: "It seems the API server is down. Please contact the DAV team."
                    });
                    deferred.rejectWith(this, arguments);
            }
        });
    }
    tryit();
    return deferred.promise();
}