web-dev-qa-db-ja.com

複数の同時待機操作を待機しています

両方の非同期操作がトリガーされ、同時に実行する機会が与えられるように、次のコードを変更するにはどうすればよいですか?

const value1 = await getValue1Async();
const value2 = await getValue2Async();
// use both values

このようなことをする必要がありますか?

const p1 = getValue1Async();
const p2 = getValue2Async();
const value1 = await p1;
const value2 = await p2;
// use both values
29
Ben

私はこれがうまくいくと思う:

 const [value1, value2] = await Promise.all([getValue1Async(),getValue2Async()]);

理解に役立つ場合のより詳細な例を以下に示します。

const promise1 = async() => {
  return 3;
}

const promise2 = async() => {
  return 42;
}

const promise3 = async() => {
  return 500;
  // emulate an error
  // throw "something went wrong...";
}

const f1 = async() => {

  try {
    // returns an array of values
    const results = await Promise.all([promise1(), promise2(), promise3()]);
    console.log(results);
    console.log(results[0]);
    console.log(results[1]);
    console.log(results[2]);

    // assigns values to individual variables through 'array destructuring'
    const [value1, value2, value3] = await Promise.all([promise1(), promise2(), promise3()]);

    console.log(value1);
    console.log(value2);
    console.log(value3);

  } catch (err) {
    console.log("there was an error: " + err);
  }

}

f1();
7
Kai

.catch()およびPromise.all()を使用します

拒否を正しく処理し、未処理の拒否に直面することなくPromises.all()を安全に使用できることを確認してください。 (編集:議論ごとの説明:エラー_unhandled rejection_ではなく、単にコードで処理されない拒否。Promise.all()は最初のプロミスの拒否をスローし、ignore残り)。

以下の例では、[[error、results]、...]の配列が返され、結果やエラーの処理を容易にします。

_let myTimeout = (ms, is_ok) =>
  new Promise((resolve, reject) => 
    setTimeout(_=> is_ok ? 
                   resolve(`ok in ${ms}`) :
                   reject(`error in ${ms}`),
               ms));

let handleRejection = promise => promise
  .then((...r) => [null, ...r])
  .catch(e => [e]); 

(async _=> {
  let res = await Promise.all([
    myTimeout(100, true),
    myTimeout(200, false),
    myTimeout(300, true),
    myTimeout(400, false)
  ].map(handleRejection));
  console.log(res);
})();_

ただし、catch()内からスローしてすべての待機を停止する(および残りの結果を破棄する)ことができます-try/catchブロックごとに1回だけ実行できるため、has_thorwnフラグを維持して確認する必要があります未処理のエラーは発生しません。

_let myTimeout = (ms, is_ok) =>
  new Promise((resolve, reject) =>
    setTimeout(_=> is_ok ?
                   resolve(`ok in ${ms}`) :
                   reject(`error in ${ms}`),
               ms));

let has_thrown = false;

let handleRejection = promise => promise
  .then((...r) => [null, ...r])
  .catch(e => {
    if (has_thrown) {
      console.log('not throwing', e);
    } else {
      has_thrown = 1;
      throw e;
    }
  });

(async _=> {
  try {
    let res = await Promise.all([
      myTimeout(100, true),
      myTimeout(200, false),
      myTimeout(300, true),
      myTimeout(400, false)
    ].map(handleRejection));
    console.log(res);
  } catch(e) {
    console.log(e);
  }
  console.log('we are done');
})();_
0
niry

約束の代わりに解決する

const wait = (ms, data) => new Promise( resolve => setTimeout(resolve, ms, data) )
const reject = (ms, data) => new Promise( (r, reject) => setTimeout(reject, ms, data) )
const e = e => 'err:' + e
const l = l => (console.log(l), l)

;(async function parallel() {

  let task1 = reject(500, 'parallelTask1').catch(e).then(l)
  let task2 = wait(2500, 'parallelTask2').catch(e).then(l)
  let task3 = reject(1500, 'parallelTask3').catch(e).then(l)

  console.log('WAITING')

  ;[task1, task2, task3] = [await task1, await task2,  await task3]

  console.log('FINISHED', task1, task2, task3)

})()

他の回答で指摘されたように、拒否された約束は未処理の例外を発生させる可能性があります。
この1つ.catch(e => e)は、エラーをキャッチしてチェーンに渡し、resolveの代わりにrejectingへの約束を許可する、すてきな小さなトリックです。 。

このES6コードを見つけた場合、見苦しい here

0
Qwerty