web-dev-qa-db-ja.com

Bluebird Promiseのシリアル反復、および変更されたアレイへの解決?

データベースに新しいItemドキュメントが見つからない場合は作成し、以前に作成したCollectionドキュメントに保存するというこの約束があります。

コレクションドキュメントは配列の最初の文字列であり、配列内の後続のインデックスは1つ以上のアイテムドキュメントに変換されます。

Promise.each "変更されていない元の配列に解決" したがって、_Promise.each_内の最後のreturnはオブジェクトをレンダリングしますが、後続の_.then_は元の配列..

これが約束です(読みやすさのために省略されています):

_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;
});
_

そして、これがPromise.each内の最後の_console.log_です。

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

そして、後続の.then(function(allItems) {の後に、最後の_console.log_があります。

_allItems: [ 
[ 'collectionName', 'one', 'two' ]
_

また、_= Promise.each_が後でPromise.joinでitemSeriesをレンダリングする変数undefined

9
Stacks

.each関数は、チェーンを介して渡される値を変更しません。

私が想定する入力として、コードを簡略化しました。

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

コードの場合:

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

これは配列itemsの解決された値であるため、結果は['one','two']のままになります。それぞれの戻り値は、チェーンされたthenに渡される値の内容には影響しません。

一方、.map関数には次の効果があります。

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

ここでは、return値の値を使用して新しい配列を作成し、それをthenに渡します。ここでは、結果は['one.','two.']になります。

コードに表示される2つのallItemsは異なるオブジェクトです。

[〜#〜] edit [〜#〜]マッピングを使用した連続反復では、次のようなヘルパー関数を記述します。

 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();
 }

ソース: Implement Promise.series

24
t.niese

BluebirdはネイティブにmapSeriesを実装するようになりました。 http://bluebirdjs.com/docs/api/promise.mapseries.html を参照してください。

また、残念ながらv3.x.xではPromise.eachが元の配列を返すように見えます。

1
Adam Reis