javascript Bluebird Promise 串行迭代,并解析为修改后的数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28736452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 09:28:18  来源:igfitidea点击:

Bluebird Promise serial iteration, and resolve to modified array?

javascriptnode.jspromisebluebird

提问by Stacks

I have this promise that creates a new Itemdocument if it's not found in the db, and then stores it in a previously created Collectiondocument..

我有这个承诺,Item如果在数据库中找不到它,它会创建一个新文档,然后将它存储在以前创建的Collection文档中。

The Collection document is the first string in an array, and any subsequent index in the array translates to one or more Item docs.

Collection 文档是数组中的第一个字符串,数组中的任何后续索引都会转换为一个或多个 Item 文档。

Promise.each "Resolves to the original array unmodified"and so the last returnwithin the Promise.eachis rendering the objects, but the subsequent .thenproduces the original array..

Promise.each “解析为原始数组未修饰的”等等,最后return内的Promise.each被渲染的对象,但在随后.then产生原始阵列..

Here's the promise (abbreviated for readability):

这是承诺(缩写为可读性):

globalVar = true;
collectionId = "";
var itemSeries = Promise.each(items, function(element) {
    if (globalVar == true) {
        return Models.Collection.findOneAsync({
            "name": element
        })
        .then(function(collection) {
            // promise chain similar to the following else..
            // set the collectionId var to an _id
        });
    } else {
        return Models.Items.findOneAsync({
            "name": element
        })
        .then(function(item) {
            if (item == null) {
                return Models.Labels.findOneAsync({
                    "title": element
                })
                .then(function(label) {
                    var newItem = new Models.Items({
                        name: element,
                        label: label._id
                    });
                    return newItem.saveAsync();
                }).then(function() {
                    return Models.Items.findOneAsync({
                        "name": element
                    });
                }).then(function(item) {
                    item.collection = collectionId;
                    return item.saveAsync();
                }).then(function() {
                    return Models.Items.findOneAsync({
                        "name": element
                    });
                }).then(function(item) {
                    allItems.push(item);
                    console.log("allItems: [ ");
                    console.log(allItems);
                    return allItems;
                });
            }
        });
    }
}).then(function(allItems) {
    console.log("allItems: [ ");
    console.log(allItems);
    return allItems;
});

And here's the last of the console.logwithin the Promise.each:

console.log是 Promise.each 中的最后一个:

allItems: [ 
[ { _id: 54eec5f2b9fb280000286d52,
    name: 'one',
    label: 54eec5f2b9fb280000286d51,
    collection: 54eec5f2b9fb280000286d50,
    __v: 0 },
  { _id: 54eec5f2b9fb280000286d54,
    name: 'two',
    label: 54eec5f2b9fb280000286d53,
    collection: 54eec5f2b9fb280000286d50,
    __v: 0 } ]

And then after the subsequent .then(function(allItems) {here's the last console.log:

然后在接下来的.then(function(allItems) {这里是最后一个console.log

allItems: [ 
[ 'collectionName', 'one', 'two' ]

Also, the variable itemSeriesthat = Promise.eachlater renders undefinedin a Promise.join?

另外,可变itemSeries的是= Promise.each后呈现undefined在Promise.join?

回答by t.niese

The .eachfunction will not change the value that is passedthrough the chain:

.each函数不会更改通过链传递的值:

I simplified your code, as input I assume:

我简化了你的代码,作为我假设的输入:

var items = ['one','two'];

For your code:

对于您的代码:

Promise.each(items, function(element) {
    return element+'.';
    //return Promise.resolve(element+'.');
})
.then(function(allItems) {
    console.dir(allItems);
});

The result will still be ['one','two']because this are resolved values of the array items. The returned value within the each does not influence the content of the value passed to the chained then.

结果仍然是['one','two']因为这是数组的解析值items。each 中的返回值不会影响传递给 chained 的值的内容then

The .mapfunction on the other hand will have this effect:

.map另一方面,该功能将具有以下效果:

Promise.map(items, function(element) {
    return element+'.';
    //return Promise.resolve(element+'.');
})
.then(function(allItems) {
    console.dir(allItems);
});

Here the returnvalue value will be used to create a new array which will then be passed to the then. Here the result would be ['one.','two.'].

这里的returnvalue 值将用于创建一个新数组,然后将其传递给then. 这里的结果是['one.','two.']

The two allItemsappearing in your code are different objects.

allItems出现在您的代码中的两个是不同的对象。

EDITFor serially iteration with mapping I would write a helper function like this:

编辑对于带有映射的串行迭代,我会编写一个这样的辅助函数:

 function mapSeries(things, fn) {
     var results = [];
     return Promise.each(things, function(value, index, length) {
         var ret = fn(value, index, length);
         results.push(ret);
         return ret;
     }).thenReturn(results).all();
 }

Source: Implement Promise.series

来源:实现 Promise.series

回答by Adam Reis

Bluebird now natively implements a mapSeries, see http://bluebirdjs.com/docs/api/promise.mapseries.html

Bluebird 现在本地实现了mapSeries,请参阅http://bluebirdjs.com/docs/api/promise.mapseries.html

It also looks like Promise.eachstill returns the original array unfortunately in v3.x.x.

Promise.each不幸的是,在 v3.xx 中看起来仍然返回原始数组