V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
97world
V2EX  ›  程序员

AngularJS 如何做到动态创建多个 promise 后, 以队列同步的方式依次执行?

  •  
  •   97world · 2016-03-11 23:03:29 +08:00 · 5989 次点击
    这是一个创建于 2929 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如果是两个相互依赖的 promise 可以用嵌套的方式来执行, 例如下面这样:

    var promise1 = GetPromise(1);
    
    promise1.then(function (result1) {
        var para1 = result1.para;
        var promise2 = GetPromise(para1);
        promise2.then(function (result2) {
            console.log(result2);
        }, function (msg) {
            // Handle error
        });
    }, function (msg) {
        // Handle error
    });
    

    但是如果有多个 promise 的话, 上面的做法就不能满足了, 是否有其他方式可以做到?

    18 条回复    2016-03-15 22:10:12 +08:00
    Arrowing
        1
    Arrowing  
       2016-03-11 23:13:36 +08:00
    既然没了依赖,就不需要再嵌套了。
    可以用组合 promise 。
    $q.all(promises).then(function(){}, function(){});
    chairuosen
        2
    chairuosen  
       2016-03-11 23:43:53 +08:00 via iPhone
    lz 意思是否为, n 个上下依赖的 promise 的顺序执行?
    var list,current;
    current = list.shift()();
    For item in list
    current = current.then(item)
    sox
        3
    sox  
       2016-03-11 23:56:15 +08:00
    PromiseA()
    .then(PromiseB)
    .then(PromiseC)
    huanglexus
        4
    huanglexus  
       2016-03-12 00:02:02 +08:00
    楼主貌似你没有理解 promise, 你这样写出来的 promise 和 callback hell 有什么区别?
    leofml
        5
    leofml  
       2016-03-12 00:44:25 +08:00
    ```javascript
    var promise1 = GetPromise(1);

    promise1.then(function (result1) {
    var para1 = result1.para;
    var promise2 = GetPromise(para1);
    return promise2;
    }).then(function (result2) {
    console.log(result2);
    }).catch(function (msg) {
    // Handle error
    });
    ```
    wind4
        6
    wind4  
       2016-03-12 12:40:35 +08:00
    then()可以接受一个 Promise ,然后串行执行 Promise 。
    wind4
        7
    wind4  
       2016-03-12 12:55:08 +08:00
    给一段代码,你感受一下

    function action1() {
    return new Promise(function(resolve, reject) {
    // 同步任务的演示
    if (Math.random() < 0.5) {
    return reject();
    }

    return resolve();
    });
    }

    function action2() {
    return new Promise(function(resolve, reject) {
    // 异步任务的演示
    superagent
    .get('http://www.baidu.com')
    .end(function(err, response) {
    if (err) {
    // 传递错误信息给 catch(function(err) { ... })
    return reject(err);
    }

    // 将请求信息传递给 then(function(response){ ... })
    return resolve(response);
    });
    });
    }

    Promise.resolve()
    .then(action1);
    .then(action2);
    .then(function(response) {
    // response 就是 action2 的 response
    })
    .catch(function(err) {
    // 如果是 action1 触发的 catch, err 为空
    // 如果是 action2 触发的 catch, err 等于 action2 的 err
    });

    Promise.all([
    action1,
    action2,
    ])
    .then(function(results) {
    // 获取结果
    // results[0]
    // results[1]
    })
    .catch()
    97world
        8
    97world  
    OP
       2016-03-12 18:46:34 +08:00
    @chairuosen 你是明白我的需求了..但好像我对 Promise 理解得不太透彻, 竟然看不太懂你这段代码..让我折腾一下
    chairuosen
        9
    chairuosen  
       2016-03-12 19:09:18 +08:00
    @97world list = [
    function(){
    return new Promise(...)
    },function........
    ];
    拼一个 list[0]().then(list[1]).then(list[2]).....
    zhuangzhuang1988
        10
    zhuangzhuang1988  
       2016-03-12 19:27:22 +08:00
    hantsy
        11
    hantsy  
       2016-03-12 20:16:34 +08:00
    $q.all
    97world
        12
    97world  
    OP
       2016-03-12 20:34:05 +08:00
    @chairuosen 我试了一下你说的方法, 但是有点奇怪, 每个 promise 里有一个请求, 遍历完 list, 所有的请求是一起发出的, 不是等第一个 promise 请求完毕后, 再发出第二 promise 的请求..
    chairuosen
        13
    chairuosen  
       2016-03-12 20:56:24 +08:00
    @97world 每个 function 必须是 return 一个 Promise http://fex.baidu.com/blog/2015/07/we-have-a-problem-with-promises/
    jinwyp
        14
    jinwyp  
       2016-03-12 23:48:40 +08:00
    看来 promise 楼上的很多人都没真正理解, q.all 只能解决同步 promise, 但没有解决顺序问题,如果需求是要顺序执行的 all 是不行的



    两种方法, 一种循环 然后 p = p.then()

    另一种用 array 的 reduce 就是 promises.reduce((a, b) => a.then(b))

    原来如此。被 reduce.length 麻痹了[good] //@王见充: reduce 似乎可以传 initialValue : promises.reduce((a, b) => a.then(b), Promise.resolve())//@勾三股四: reduce 确实更合适,不过这样写的话第一个项目必须是 Promise 对象… //@王见充: promises.reduce((a, b) => a.then(b))

    http://weibo.com/1712131295/DfAgvDjhc?type=repost#_rnd1457797661134

    promise 里面的细节其实还是很多的
    duhastmich
        15
    duhastmich  
       2016-03-13 15:49:35 +08:00
    Promise 创建完成就会执行了,要顺序执行肯定不能先把 Promise 创建出来,先创建一组函数,每个函数返回一个 Promise 是个办法。还以换个思路,把一个值” pipe ”到一组函数里,就像 shell 那样 https://github.com/zweifisch/promised-util/blob/c05aa70eda3a2f7735f9d86a24e7bba3a225ef62/index.js#L63-L70
    97world
        16
    97world  
    OP
       2016-03-15 22:02:32 +08:00
    @jinwyp 啊终于有人了解我的意图并指出楼上的错误了..
    97world
        17
    97world  
    OP
       2016-03-15 22:03:51 +08:00
    @duhastmich 看来我对 Promise 的了解还很不透彻, 如果不是你说 Promise 创建完就会执行, 我根本连 Promise 的执行顺序都不清楚..
    97world
        18
    97world  
    OP
       2016-03-15 22:10:12 +08:00
    @jinwyp @duhastmich 非常感谢两位! 我现在的做法就是递归+callback, 尽管这种做法并不优雅, 但总算是解决问题了, 两位提供的方案都给我了很大的启发, 我会根据两位提供的方法去重构一下这部分的代码. 再次感谢.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5408 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 08:43 · PVG 16:43 · LAX 01:43 · JFK 04:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.