这段代码中嵌套的承诺的目的是什么?

What is the purpose of the nested promise in this code?

我正在尝试熟悉 Promises 及其工作原理。虽然这对我来说是一个新概念,但我相对确定我可以理解其中的大部分内容。特别是,我一直在查看 BlueBird 库并按照我的方式完成示例。但是页面上有一个代码片段我无法完全理解。

Promise.promisifyAll(needle);
var options = {};

var current = Promise.resolve();
Promise.map(URLs, function(URL) {
    current = current.then(function () {
        return needle.getAsync(URL, options);
    });
    return current;
}).map(function(responseAndBody){
    return JSON.parse(responseAndBody[1]);
}).then(function (results) {
    return processAndSaveAllInDB(results);
}).then(function(){
    console.log('All Needle requests saved');
}).catch(function (e) {
    console.log(e);
});

在这段代码中,我了解到 needle 库正在被承诺。我想我说 current 被设置为一个空洞的承诺是正确的。

我的问题是关于

current = current.then(function () {
    return needle.getAsync(URL, options);
});
return current;

代码。如果 needle 已被 promised,将其嵌套在另一个 promise 中的目的是什么?

这是一种对异步调用进行排队并同时将它们交给 map 函数以便生成所有结果数组的承诺的可疑方法。

那么它有什么作用呢?单独排队通常是 done using reduce,带有 current 累加器的循环也是如此。它以空承诺开始,并为数组中的每个 url 重复链接一个回调;就像这段代码一样:

var current = Promise.resolve().then(function() {
    return needle.getAsync(URL[0], options);
}).then(function() {
    return needle.getAsync(URL[1], options);
}).then(function() {
    return needle.getAsync(URL[2], options);
}) …

但是,在 map 循环中使用它实际上会生成一个单一承诺数组,例如

var promises = [];
promises[0] = Promise.resolve().then(function() {
    return needle.getAsync(URL[0], options);
});
promises[1] = promises[0].then(function() {
    return needle.getAsync(URL[1], options);
});
promises[2] = promises[1].then(function() {
    return needle.getAsync(URL[2], options);
});
…

我要么使用 reduce 方式,从 Promise.resolve([]) 开始逐步添加到结果数组,要么写一个专用的 scan(或 mapAccum, 无论你想给它起什么名字) 函数并将其与 Promise.all.

结合使用

或者更好,只需使用 Bluebird 的内置 {concurrency: 1} option for Promise.map

Bergi 写了一个很好的答案,您应该阅读。以下是我使用 .each:

编写代码的方式
var get = Promise.promisify(needle.get);

Promise.each(URLs, get). // make the requests
       map(function(x){ return JSON.parse(x[1])} ). // parse response as json
       then(processAndSaveAllInDB).
       then(function(){ console.log("All Needle requests saved"); }).

请注意,您不需要 catch,因为在这种情况下,Bluebird 会发现未处理的拒绝并为您报告。

通常当人们执行上面的代码时,他们会关心顺序,尽管原始代码中不能保证顺序(map 改变了 bluebird 2 中的行为更快但不能保证排队顺序)。