2016-06-29 9 views
2

私は一連の約束が完了するのを待っています。私はPromise.allでこれを行うことができると知っていますが、それらの約束のうちの1つが約束のリストに新しい約束をするとき、何をすべきか分かりません。再帰Promise.all?

例:

asyncFunction(...).then(result => { 
    // do something 
}); 


asyncFunction(...).then(result => { 
    for(let row of result) { 
     asyncFunction(row); 
    } 
}); 


console.log(promises.length); // 2 
await Promise.all(promises); 
console.log(promises.length); // 5 

asyncFunctionのようなものである:ここに起こった何

const asyncFunction = (...args) => { 
    let result = new Promise((resolve, reject) => { 
     pool.query(...args, (err, rows, fields) => { 
      if (err) { 
       reject(err); 
      } else { 
       resolve(rows); 
      } 
     }); 
    }); 
    promises.push(result); 
    return result; 
}; 

するのでpromises.lengthしかし2で、私のpromises配列にasyncFunctionプッシュ約束への最初の二つの呼び出しということですそれらが完了するのを待ってから、Promise.allが既にその配列を評価しているので、第2のものが配列に新しい約束を押し込むので、待たれていません。

どのように私はすべての約束と新しいものを待つことができますか?この例ではawait Promise.all(promises)を2回呼び出すだけで動作しますが、これは無限になります。私は単にこれでPromise.allを交換し、正常に動作すべきだと思う

function recursiveAll(array) { 
    // Wait for the promises to resolve 
    return Promise.all(array).then(function(result) { 
     // If no new promises were added, return the result 
     if (result.length == array.length) 
      return result; 
     // If new promises were added, re-evaluate the array. 
     return recursiveAll(array); 
    }); 
} 
+1

プールに任意のタイミングで押し込まないでください。プールが満杯になるのを待ってから、 'それで' Promise.all'を呼び出します。異なる時間にプッシュする必要がある場合、 'Promise.all'を複数回呼び出す必要がある場合は、すべてを1つの配列にまとめてください。 – Bergi

+1

@Bergi新しい約束事は、以前の非同期結果の結果として作成されます。 – user2864740

+0

[this](http://stackoverflow.com/q/37801654/1048572)は役に立ちますか? – Bergi

答えて

3

while(promises.length) { 
    await promises.shift(); 
} 
+2

'prevLength'を保存する必要はありません。ちょうど' result.length'を使用することができます – Bergi

+0

ニースキャッチは、編集を行います。 – TbWill4321

+0

'return recursiveAll(array.slice(result.length))'は効率的になりませんか?新しい要素のみをチェックする。 – mpen

0

:あなたは、各反復の後にリストの状態を再評価し、すべての再帰関数を書くことができます

+1

'await'はexaclty ES6ではありません。 – Bergi

+0

@Bergiいいえ...そうではありません、私は質問を取り上げます。私の元々の質問にはすでに「待っている」がありましたが。私は待っているよりも少ないバージョンも素晴らしいだろうと思う。 – mpen

+1

この答えの問題は、* parallel *ではなく、* sequence *のすべての約束を評価することです。 – TbWill4321

3

ています副作用のある関数の問題。

あなたのコードは抽象的な抽象的な答えですが、promises-アレイを完全に削除することをお勧めします。

const asyncFunction = (...args) => { 
    return new Promise((resolve, reject) => { 
     pool.query(...args, (err, rows, fields) => { 
      if (err) { 
       reject(err); 
      } else { 
       resolve(rows); 
      } 
     }); 
    }); 
} 

asyncFunction(...).then(result => Promise.all(result.map(row => asyncFunction(row)))); 

限り、私はあなたの意図を理解するように、これは配列内の配列の入れ子構造になるはずである、最悪の場合には、今WICHのみALL取得するために平坦化する必要があります値、および前のものによってトリガーされる値。

+0

私はちょっとそれをやってみました、それはとても面倒です。その単純なループのための罰金、しかし、あなたはランダムなものの束をやっている場合、あなたは最後に 'Promise.all'を返すことができるように、これらのすべての"緩い "約束を収集する必要があります。私はちょうど何かを自動化したかった個々の約束事がすべて完了したとき、私がすべて終わったときには、私は気にしません。 – mpen

+0

私は同意しますが、コードサンプルの抽象度のレベルのために、私はあなたに良い例/答えを与えることはできません。多分あなたは具体的な問題を示すことができるので、実際のコードでこれについて議論することができます。 – Thomas

+0

_副作用のある関数には問題があります._良い答え! – ftor