延迟承诺 - 每次完成后逐个运行函数

时间:2017-05-04 13:36:01

标签: javascript jquery promise deferred

我有3个函数可以对后端系统进行异步调用:fnOne,fnTwo,fnThree。我知道我没有正确地做到这一点,但无法找到正确的方法。

我开始尝试在每次完成后调用它们:

然而,fnOne内部已经有一个延迟对象,当它被解决时,它正在解决我的承诺。

$.when(oController._fnOne()).done(function(){
    console.log("fn one complete");
});

功能

_fnOne: function(){

    var oController = this;

 //when the deferred is done in _checkInstanceStatus, it is resolving the above, rather than the pDeferred in this function resolving the above.
$.when(oController._checkInstanceStatus(oParams)).done(function(oStatusData) {
        //does some stuff 
        return $.Deferred(function() {
            var pDeferred = this;
            //does a call for data and upon success i will resolve ..
            pDeferred.resolve();
        });
    });
}

其他功能

_checkInstanceStatus: function(oParams){
            return $.Deferred(function() {
                var pDeffered = this;
                //does a call for data and upon success i will resolve...
                pDeffered.resolve(data);

                });
            });
        },

然后计划是尝试链接它们,所以它们一个接一个地运行,如下:

$.when(oController._fnOne())
.then(oController._fnTwo())
.then(oController._fnThree())
.done(function(){
    console.log("all complete!");
});

2 个答案:

答案 0 :(得分:3)

有几件事:

  1. 如果您将单个Deferred传递给$.when,则无需使用fnOne

  2. _checkInstanceStatus(可能是其他人)需要返回承诺/延期,以便您知道何时完成。由于它使用then,它返回Deferred,因此可以使用fnOne来执行此操作:

  3. 所以fnOne: function() { var oController = this; return oController.__checkInstanceStatus(oParams).then(function(oStatusData) { var pDeferred = $.Deferred(); callAmazon(function() { if (/*successful*/) { pDeferred.resolve(); } else { pDeferred.reject(); } }); return pDeferred.promise(); // Or just the Deferred if you like, but // normally you want to share promises, not // Deferred objects }); } 可能如下所示:

    then

    注意如何返回调用then的结果,这是通过调用then创建的承诺。该承诺将根据您从oController._fnOne() .then(oController._fnTwo) // Notice no () on that, we're passing the .then(oController._fnThree) // function in, not calling it. Same on this line. .then(function() { console.log("all complete!"); }) .catch(function(error) { // Do something about the error }); 处理程序返回的承诺来解决。

    您使用与其他功能相同的模式。

    要一个接一个地链接它们,你要这样做:

    _fnOne

    (我假设fnOneDeferred功能相同。)

    我假设一个相对较新版本的jQuery,它在Deferreds中支持Promises。

    旁注:我转而使用原生Promise(必要时使用polyfill来支持旧浏览器),而不是使用jQuery的fnOne: function() { var oController = this; return oController.__checkInstanceStatus(oParams).then(function(oStatusData) { return new Promise(function(resolve, reject) { callAmazon(function() { if (/*successful*/) { resolve(); } else { reject(); } }); }); }); } ,它有......好吧,它有很多历史和API变得繁琐。 : - )

    有本地承诺:

    {{1}}

    用法是相同的(因为我使用了在第一个示例中添加到Deferred的Promise API)。

答案 1 :(得分:2)

理解你的功能非常困难。所以我简单地用3种不同的方式定义3个新的func,这样你就可以更容易理解jquery延迟。

var funcOne = function() {
  var defer = $.Deferred();
  $.ajax('/echo/json')
    .then(function(data) {
      console.log('func1', data);
      return defer.resolve(data);
    });
  return defer;
}

var funcTwo = function() {
  console.log('begin call func 2');
  return $.ajax('/echo/json')
    .then(function(data) {
      console.log('func2', data);
      return $.Deferred().resolve(data);
    });
}

var funcThree = $.ajax('/echo/json');

funcOne()
  .then(funcTwo)
  .then(funcThree)
  .then(function(data) {
    console.log('finally got func 3 data', data)
  });

jsfiddle链接:https://jsfiddle.net/zmjLaznn/