2016-12-13 5 views
0

配列全体を反復処理し、すべてのオブジェクトをデータベースに保存する必要があります。配列を反復処理してオブジェクトを保存した後のコールバック

最後に、保存されたオブジェクトと失敗したオブジェクトのすべてをarrayとするコールバックが必要です。作品上記

exports.addList = (app, body, callback) => { 
var savedObjects = [] 
var failedObjects = [] 

body.forEach((element, index) => { 
    body[index] = _.pick(element, 'userAId','userBId') 

    db.List.create(element).then((list) => { 
     savedObjects.push(element) 
     if (index == body.length - 1) { 
      callback(savedObjects, failedObjects) 
     } 
    }).catch((error) => { 
     if (error.name === "SequelizeUniqueConstraintError") { 
      failedObjects.push(element) 
      if (index == body.length - 1) { 
      callback(savedObjects, failedObjects) 
     } 
    }) 
}) 
} 

コード:以下

は、私が持っているコードです。これを達成するための方法はありますか?

+0

これは現在どのように機能していますか?これを[Code Review](http://codereview.stackexchange.com/)にも投稿する価値があります。 –

+0

これはあなたが必要とするものを達成するための合理的な方法です。いくつかの繰り返しを切っておきたい場合は、あなたの約束をチェーンの終わりに1回の 'finally'コールで入れ、' then'と 'catch'ハンドラからそれを取り除くことができます。 –

+0

ありがとうございます。私はjavascriptが新しく、これが正しいかどうかは分かりませんでした。 @ JordanBurnett私はコードDRYを維持するためにリファクタリングします。 – user1107173

答えて

0

あなたの例では、完全なコールバックは、最初の約束が完了した後に常に起動します。これは、create関数が非同期で周囲のループが存在しないためです。したがって、最初のコールバックがトリガーされるまでにループは既に完了しているためです。

この場合、elementindexは常にループの最後になります。これを回避する方法の1つは、あなたの約束をそれ自身の機能に移すことでしょう。

この例では、completeメソッドをトリガーする完了した約束の数を追跡するために余分なフラグを使用しました。

exports.addList = (app, body, callback) => { 
    var savedObjects = [] 
    var failedObjects = [] 
    var complete = 0; 

    function createElement(element){ 
    db.List.create(element).then((list) => { 
     savedObjects.push(element) 
    }).catch((error) => { 
     if (error.name === "SequelizeUniqueConstraintError") { 
      failedObjects.push(element) 
     } 
    }).finally(() => { 
     complete++; 
     if(complete == body.length) { 
      callback(savedObjects, failedObjects) 
     } 
    }); 
    } 

    body.forEach((element, index) => { 
    body[index] = _.pick(element, 'userAId','userBId'); 
    createElement(element); 
    }) 
} 
+0

'db.List.create()'を並行して実行したい場合は、 'Promise.all()。then()'でこれを行うこともできます。 – doublesharp

1

それはPromiseを返しますように私は、並列にdb.List.create()を実行するためにPromise.all()を使用して、次のアプローチをお勧めします。 mappingbodyの配列要素をPromisesに変更すると、パラレルで実行され(completeの数を追跡する必要がないため)、パフォーマンスが向上します。

exports.addList = (app, body, callback) => { 
    var savedObjects = []; 
    var failedObjects = []; 

    Promise.all(
    // map the array to return Promises 
    body.map(element => { 
     const list = _.pick(element, 'userAId','userBId'); 
     return db.List.create(list) 
     .then(() => savedObjects.push(list)) 
     .catch((error) => { 
     if (error.name === 'SequelizeUniqueConstraintError') { 
      failedObjects.push(list) 
     } 
     }) 
    }) 
) 
    // when all Promises have resolved return the callback 
    .then(() => callback(savedObjects, failedObjects)); 
} 
関連する問題