search

Home  >  Q&A  >  body text

angular.js - 怎么写promise的链式调用

比如我有一个A.func1()是异步的,它能返回一个对象x1,我还有一个B.func2()也是异步的,需要根据x1来执行,然后B.func2返回一个最终值值t,根据这个最终值t就进行一些提示性显示。请问这个要怎么写呢?
我自己写的代码是这样的

A.func1().
    then(function(x1) {
        B.func2(x1).
            then(function(t) {
                //do something
            })
    })

但是感觉这样用不用then就一个效果啦……还是变回金字塔了

高洛峰高洛峰2743 days ago516

reply all(4)I'll reply

  • 世界只因有你

    世界只因有你2017-05-15 16:53:30

    In response to the supplementary comment in the comments about "saving state during continuous calling of promises", I would like to elaborate on several strategies

    The best strategy: De-statement

    That is, adjust your logic so that the calling process of A.func1, B.func2, and the anonymous function (let’s call it func3) does not contain state, that is, let func3 only rely on the output of func2 and not the output of func1. ; Or let func2 not depend on func1, use something like Promise.all to get the results of func1 and func2 at the same time and throw them to func3

    Central strategy: "global" variables maintain status

    Advantages: state can be extended state.x2 .x3...
    Problem: If a long call chain has complex states, it is easy to contaminate bugs, and the maintainability of the code will be seriously reduced

    js
    function yourLogic() { var state = {}; return A.func1() .then(function(x1) { state.x1 = x1; return B.func2(x1); }) .then(function(t) { //play with t & state.x1 return yourResult; }); }
    The bind method of

    bluebird can bind thisArg and can be used to retain the state. The principle is the same

    js
    function yourLogic() { return A.func1() .bind({})//新建空对象用于保留状态 .then(function(x1) { this.x1 = x1; return B.func2(x1); }) .then(function(t) { //play with t & this.x1 return yourResult; }); }

    Choice: Temporary additional delivery

    Advantages: Without state, if the call chain is long, this extra state is controlled between two steps, maintaining better maintainability and less prone to bugs
    Disadvantages: If each step of the long call chain has a state, it will become extremely verbose

    js
    function yourLogic() { return A.func1() .then(function(x1) { return B.func2(x1) .then(function(t) { return { t: t, x1: x1 } }); }) .then(function(state) { //play with state.t & state.x1 return yourResult; }); }

    Of course, the inner then here can also be encapsulated and optimized by yourself

    js
    function yourLogic() { return A.func1() .then(function(x1) { return keepState(B.func2(x1), { x1: x1 }, 't'); }) .then(function(state) { //play with state.t & state.x1 return yourResult; }); } function keepState(promise, state, key) { return promise.then(function(value) { state[key] = value; return state; }); }

    Last solution: Closures maintain state

    This is actually the original way of writing the question. I think the main problem is that the question has been downgraded back to the original "callback hell" or the embarrassment of the callback pyramid

    The advantage is...it works

    js
    function yourLogic() { return A.func1() .then(function(x1) { return B.func2(x1) .then(function(t) { //play with t & x1 return yourResult; }); }) }

    reply
    0
  • 世界只因有你

    世界只因有你2017-05-15 16:53:30

    The object directly in then 里面返回一个 Promise, as follows:

    javascript
    A.func1() .then(function (x1) { return B.func2(x1); }) .then(function (t) { // do something });

    In response to the problem mentioned in your comment, if you do not use a third-party Promise library, you can use it as follows:

    javascriptvar promise = new Promise(function (resolve, reject) {
        var firstValue;
        A.func1()
            .then(function (x1) {
                firstValue = x1;    // 临时保存
                return B.func2(x1);
            }, reject)
            .then(function (x2) {
                resolve({
                    firstValue: firstValue,
                    secondValue: x2
                });
            }, reject);
    });
    
    promise.then(function (result) {
        console.log(result);    // {"firstValue": "Hello", "secondValue": "World"}
    });
    

    Using third-party Promise libraries can simplify this process.

    reply
    0
  • 巴扎黑

    巴扎黑2017-05-15 16:53:30

    Promise will return a promise object, so that it can use elegant chain calls.

    reply
    0
  • 过去多啦不再A梦

    过去多啦不再A梦2017-05-15 16:53:30

    If the return value of the function in then is a direct quantity, it will be used as the parameter of then in the next chain call.
    If the return value has the interface of promise, the result of the resolve of the promise is returned.
    Using q as an example

    var q = require('q');
    
    var a = function(){
      var d = q.defer();
    
      d.resolve(1);
      return d.promise;
    };
    
    a().then(function(r){
      console.log(r); // 此处是1
      return 2;
    }).then(function(r){
      console.log(r);  // 此处2,是由上一个then返回的
      var d = q.defer();
      d.resolve(3);
      return d.promise;
    }).then(function(r){
      console.log(r); // 此处是3,由上一个then返回的promise的resolve提供.当需要异步调用时直接return的值肯定不够用,这时就需要返回promise对象.
    });

    reply
    0
  • Cancelreply