2017-05-04 30 views
1

我有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!"); 
}); 
+0

恐怕是不太足够的信息,在这个问题给你一个坚实的答案。例如,“fnOne”所做的“打电话”是什么?这是否会返回Promise或Deferred? –

+0

@ T.J.Crowder感谢您的回复,调用是调用数据后端系统的地方,在解决延迟后,调用已成功完成pDeferred.resolve(); – neeko

+0

这个对后端系统的调用是通过'$ .ajax'来实现的吗?再次说明:它是否会返回Promise或Deferred,或者? –

回答

3

几件事:

  1. 如果您传递单个Deferred,则不需要使用$.when

  2. fnOne(大概其他)需要回报承诺/递延,让你知道当它完成。由于它的使用_checkInstanceStatus,它返回一个延迟,它可以做,通过使用then

所以fnOne可能是这样的:

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 
}); 

(我假设_fnOnefnOne是相同的功能。)

我假设相对最近版本的jQuery在Deferreds中有Promises支持。


附注:我会切换到使用本地的承诺(以在必要时支持旧的浏览器填充工具),而不是使用jQuery的Deferred,其中有...好,它有很多的历史和的API变得繁琐。:-)

随着原生承诺:

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

Appologies,我的一些错字在尝试简化代码的同时,也非常感谢!我已经切换到了本机承诺 – neeko

+0

最后一个问题对你来说如何将数据从一个函数传递到下一个函数? – neeko

+1

@neeko:您将它作为参数传递给'resolve',并将其作为目标函数中的参数接收。例如,如果'_fnOne'执行resolve(“foo”)',则_fnTwo'上方的链第一个参数的值是'“foo”'。:-) –

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/