【问题标题】:Serialized Execution of an Array of Promise Chains in BluebirdBluebird 中一系列 Promise 链的序列化执行
【发布时间】:2016-04-30 03:17:27
【问题描述】:

我正在尝试构建一组 Promises 链并让它们按顺序执行。每个链在数组中的下一个条目执行之前完成。例如:[connect1, connect2, connect3],其中每个“任务”都包含一系列步骤。

我遇到的一个大问题是能够构建链并将其添加到数组中——因为它已经开始执行了。

我一直在玩的一些测试代码在这里:

function step1() {
    return new Promise(resolve => {
        // Normally something asnyc here
        console.log("step1:", this);
        resolve();
    });
}
function step2() {
    return new Promise(resolve => {
        // Normally something asnyc here
        console.log("step2:", this);
        resolve();
    });
}
function step3() {
    return new Promise(resolve => {
        // Normally something asnyc here
        console.log("step3:", this);
        resolve();
    });
}

function promiseSeq( tasks, state ) {

    let current = Promise.resolve();
    for (let k = 0; k < tasks.length; ++k) {
        var taskWithState = tasks[k];
        if (typeof state !== 'undefined') {
            taskWithState = taskWithState.bind(state);
        }
        current = current.then(taskWithState);
    }
    return current;

}

function buildChain(idx) {

    // Build the connection chain (with state)
    //------------------------------
    var s = { conn: idx }; // some state
    var q = [ step1, step2, step3 ];
    return promiseSeq(q, s);
}

function streamConnect() {

    // Build array of chains
    //------------------------------
    var q = [ ];
    q.push(buildChain(1)); // e.g. connect1
    q.push(buildChain(2)); // e.g. connect2
    q.push(buildChain(3)); // e.g. connect3

    var p = Promise.each(q, function(f) {return ( f )});

    // Process promises...
    p.then(function()     {console.log("done")})
     .catch(function(err) {console.error("catch:",err)})

    return;

}

一旦我有了数组中每个“任务”的链,我想按顺序执行链。所以我的目标是让输出成为:

step1: Object {conn: 1}
step2: Object {conn: 1}
step3: Object {conn: 1}
step1: Object {conn: 2}
step2: Object {conn: 2}
step3: Object {conn: 2}
step1: Object {conn: 3}
step2: Object {conn: 3}
step3: Object {conn: 3}

我看到的是我的代码:

step1: Object {conn: 1}
step1: Object {conn: 2}
step1: Object {conn: 3}
step2: Object {conn: 1}
step2: Object {conn: 2}
step2: Object {conn: 3}
step3: Object {conn: 1}
step3: Object {conn: 2}
step3: Object {conn: 3}

谈到 Promises 时,我很不适应,我正在努力理解(没有特定的顺序): 1. 为什么 promise 的执行似乎是交错的(所有 step1 都完成了,然后是 step2,等等)? 2.我怎样才能得到我预期的输出以上的序列化执行行? 3. 可以延迟设置链吗?我看到我的线路 current = current.then(taskWithState); 最终使用 Bluebird 调用 async.invoke,但我没有找到避免这种情况的方法。

任何建议或帮助将不胜感激。

【问题讨论】:

    标签: javascript promise bluebird


    【解决方案1】:

    您的buildChain() 函数执行您的操作。它会立即开始运行它们。

    所以,这段代码:

    var q = [ ];
    q.push(buildChain(1)); // e.g. connect1
    q.push(buildChain(2)); // e.g. connect2
    q.push(buildChain(3)); // e.g. connect3
    

    立即开始运行所有三个链。所以,你有三个并行运行的 Promise 链,而不是按顺序运行。

    仅供参考,这行代码应该是一个有趣的线索:

    var p = Promise.each(q, function(f) {return ( f )});
    

    因为当Promise.each() 调用它的回调时,你实际上并没有做任何事情。因此,您没有赋予它任何对您的操作的控制权。它们在Promise.each() 运行之前就已经启动了。


    您可以使用Promise.each() 来解决此问题,但您需要按预期使用它。它希望您向它传递一个数组和一个对数组中的项目进行操作的迭代器。你没有做那样的事情。你正在向它传递一个已经开始执行的承诺数组。


    您可以通过将streamConnect() 更改为此来修复它:

    function streamConnect() {
    
        var q = [1,2,3];
    
        var p = Promise.each(q, function(item) {
            return buildChain(item);
        });
    
        // Process promises...
        p.then(function() {console.log("done")})
         .catch(function(err) {console.error("catch:",err)})
    
        return;
    
    }
    

    这不会开始执行 Promise.each() 调用的每个链 UNTIL。

    工作演示:https://jsfiddle.net/jfriend00/3ce0ceuy/

    【讨论】:

    • 非常感谢您的详细回复。这现在更有意义了。
    猜你喜欢
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-15
    • 1970-01-01
    • 2016-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多