7

このスタイルを学ぶために、既存のプログラムをasync/awaitを ( 経由でBabel)使用するように移行しています。bluebirdCoroutines私はこのチュートリアルを見てきました。

以下の動作に少し困っています。このスニペットは期待どおりに機能します。

let parts = [];
let urlsP = urls.map((url, index) => { 
    return dlPart(url, index, tempDir); 
});
for (let urlP of urlsP) { // Parallel (yay!)
    parts.push(await urlP);
}
for (let part of parts) { // Sequential
    await appendFile(leFile, part);
}

次のように書き直すと、まだ機能しますが、最初の操作はもはや並列ではありません (完了するまでにはるかに時間がかかります)!

let index = 0;
let parts = [];
for (let url of urls) { // NOT Parallel any more!!!
    index++;
    parts.push(await dlPart(url, index, tempDir));
}
for (let part of parts) {
    await appendFile(leFile, part);
}

これはの実装ですdlPart()

function dlPart(url, num, dir) {
    var cmd = 'wget --quiet "' + url + '" -O ' + dir + "/" + num;
    return exec(cmd).then(() => {
        return dir + '/' + num;
    });
}

私は何が欠けていますか?

4

3 に答える 3

4

The reason that it is no longer running in parallel is because of the timing of when you are creating your promises in the two examples. This is described above comment more clearly.

In your first example you start all the Promises which begin to execute their functions. Then in this loop:

for (let urlP of urlsP) { // Parallel (yay!)
    parts.push(await urlP);
}

You wait for the first promise to be done, and then the second promise to be done, etc. But the whole time you are waiting for the first promise to be done ALL the other promises are still executing. Hence they run in "parallel".

In your second example, you both START and AWAIT the promises inside the loop instead of starting them all before the loop. So in this code:

for (let url of urls) { // NOT Parallel any more!!!
    index++;
    parts.push(await dlPart(url, index, tempDir));
}

The parts.push line does the following in order:

  1. Runs dlPart() which returns a promise and starts downloading the part
  2. Waits for the promise to resolve
  3. Pushes the resolved value into parts.

All the other promises have not been started and are not running "in parallel" they only get started when it's their turn in the loop. This means they get called one at a time, and only start the next one executing once the previous one is done and that is why they run iteratively.

Note: .map is not asynchronous if it were then your first example wouldn't work with large lists because the for of loop would start before all the promises were added to your urlsP array.

于 2015-10-15T21:21:53.390 に答える
2

関数は非同期であるため、コードの残りの.map部分は待機する必要がなく、準備ができたら終了します。for loop次に、完了するまですべてを保持するに置き換えました。

于 2015-06-06T00:12:42.963 に答える