使用bluebird .reduce

时间:2018-04-09 11:50:54

标签: javascript node.js bluebird

我已经找到了许多减少相关问题的承诺,但没有什么能够帮助我解决我的特殊问题所以请原谅我,如果我最终错过了与我的问题有关的问题,可能对其他人来说很明显。

简而言之:我有一个节点脚本需要在一堆不同的文件上进行链接操作,这些操作是异步的,包含在promises中,但最终由于各种原因我希望文件处理按顺序进行。

我最终使用了Bluebird的承诺的 .reduce 功能,但我无法理解我应该如何将参数传递给它。

以下简化示例总结了我的问题的核心:

const Promise = require('bluebird');

var f = (string) => {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log(string);
            resolve();
        }, 3000);
    })
    .catch(err => {
        console.error(err);
    });
};

var strings = ["hello", "world"];

strings.reduce((current, next) => {
    return f(current).then(f(next));
}, Promise.resolve([]))
.then(() => {
    console.log("All done!");
})
.catch(err => {
    console.error(err);
});

我所期待的以及我需要脚本做的是让它按顺序对一组参数执行promise。 我得到以下输出:

hello // after 3s
world // after 3s
All done! // after 3s

我想要的是:

hello // after 3s
world // after 6s
All done! // after 6s

据我所知,问题是promises会在创建后立即执行,并且我会使用 f(下一个)在第一个实例的同时创建第二个实例

我也知道使用没有参数的promises,即带有硬编码 console.log(“hello”)的f1和带有硬编码 console.log(“world”)的f2 在使用

时按预期工作
return f1.then(f2);

但我无法解决如何保持异步时序,同时将参数传递给它的所有方法。 提前感谢您的时间和帮助,过去24小时我一直在为此而烦恼。

1 个答案:

答案 0 :(得分:1)

您在每次迭代时对f进行两次调用,您只需要一次,并且您希望所做的那次等待之前的承诺解决 - 所以你不能做.then(f(next))因为不等待,你需要传递一个函数。 (另外,因为你从不使用第一个promise的分辨率值,所以不需要给它一个空数组。)

所以进行两项修改(一次调用,并传入一个函数):

strings.reduce((p, next) => {        // ***
    return p.then(() => f(next));    // *** Main changes here
}, Promise.resolve())                // ***
.then(() => {
    console.log("All done!");
})
.catch(err => {
    console.error(err);
});

实例(暂停时间较短):

var f = (string) => {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log(string);
            resolve();
        }, 1000);
    })
    .catch(err => {
        console.error(err);
    });
};

var strings = ["hello", "world"];

strings.reduce((p, next) => {        // ***
    return p.then(() => f(next));    // *** Main changes here
}, Promise.resolve([]))              // ***
.then(() => {
    console.log("All done!");
})
.catch(err => {
    console.error(err);
});

我还重命名了current参数p,因为它不是strings中的“当前”条目,而是reduce累加器的先前值。

或者使用简洁的箭头功能:

strings.reduce((p, next) => p.then(() => f(next)), Promise.resolve())
.then(() => {
// ...