我已经找到了许多减少相关问题的承诺,但没有什么能够帮助我解决我的特殊问题所以请原谅我,如果我最终错过了与我的问题有关的问题,可能对其他人来说很明显。
简而言之:我有一个节点脚本需要在一堆不同的文件上进行链接操作,这些操作是异步的,包含在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小时我一直在为此而烦恼。
答案 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(() => {
// ...