2017-04-04 13 views
0

iが同様のオブジェクトの配列を有する:のNode.js:非同期タスクの順次実行

let builds = [ 
    { status: "Failed"}, 
    { status: "Completed"}, 
    { status: "Building"}, 
    { status: "Building"}, 
    { status: "Failed"}, 
    { status: "Cancelled"}, 
    ... 
] 

要素の数が変化し、それぞれのstatusもゼロの最小アレイサイズで、変化するであろう。

私は希望機能書く必要が

:へのアレイを介し

  • 反復をしてCancelled
  • するとそこにstatus
  • Buildingの更新それらの項目の statusで任意の項目を探してください Buildingが出現しなくなりました。 { status: "Building" }

catchは、配列がMongoDBに格納されているため、各操作を非同期の方法でDBに永続化する必要があります。私はすべてのことについてQの約束を使用しています。これを行うに

私の試みは、現時点では次のようになります。

let count=0; // Keep track of how many "builds" in "Building" state 

module.getAllBuilds((builds) => { 
    builds.forEach((build) => { 
     if (build.status == "Building") { 
      count++; 
      module.cancelBuild(build) 
      .then(() => { 
       if (!--count) { // When counter is zero, all builds have been dealt with. 
        module.newBuild(); 
        return; 
       } 
       }) 
     } 
    }) 
    module.newBuild(); // Get here if the build array is empty or no builds in "Building" state 
}) 

私は多くのスタックのように、Building状態のエントリ数を追跡するためにcount変数を使用しています。スタックが空の場合は、新しいビルドの作成に進みます。

問題は、いずれかのビルドがBuilding州にあるかどうかによって、2つの場所のいずれかにを呼び出す必要があるということです。

これを実装するより良い方法はありますか?ただ「ビル」のためのアレイを構築するフィルタリングによって最初に

+0

あなたのコードが非同期タスクを「順番に」実行していることを理解していますか? –

+0

これは逐次実行することを意図しています。 – mstubbies

答えて

0

- それは読みやすくしようとしている(と失敗)、

module.getAllBuilds((builds) => builds.filter(build => build.status == 'Building').reduce((promise, build) => promise.then(()=> module.cancelBuild(build)), Promise.resolve()) 
.then(() => module.newBuild())) 

を次のように、あなたのコードを簡素化することができますArray#reduceを使用したか:P

module.getAllBuilds((builds) => 
    builds.filter(build => build.status == 'Building') 
    .reduce(
     (promise, build) => promise.then(() => module.cancelBuild(build)), 
     Promise.resolve() 
    ) 
.then(() => module.newBuild())) 

またはtranspiled ES5バージョン

module.getAllBuilds(function (builds) { 
    return builds.filter(function (build) { 
     return build.status == 'Building'; 
    }).reduce(function (promise, build) { 
     return promise.then(function() { 
      return module.cancelBuild(build); 
     }); 
    }, Promise.resolve()).then(function() { 
     return module.newBuild(); 
    }); 
}); 

注:module.newBuild()は、「ビルド」がない場合でも呼び出されますbuilds

+0

最初のスニペットの 'reduce'引数の字下げは私を驚かせます... – Bergi

+0

ええ、私も - コード全体はもともと2行で、読みやすくするようにしました。失敗しました:pあなたがそれをより良い "フォーマット"する方法について考えているなら、@Bergi –

+0

うわー、それは深いです。それは確かに "短くて​​簡潔な"ボックスをチェックしています。私はreduce()をどのように使用しているかについて100%明確ではありません。私はfilter()を最初に使い、argsをreduce()にしますが、reduce()の本体は少しのブードゥーです。 "Promise.resolve()"は次の反復のために返されますか? – mstubbies