1. ホーム
  2. javascript

[解決済み] Promise() コンストラクタの内部で async/await を使用するのはアンチパターンでしょうか?

2022-05-11 17:30:45

質問

を使用しています。 async.eachLimit 関数を使用して、一度に実行できる操作の最大数を制御します。

const { eachLimit } = require("async");

function myFunction() {
 return new Promise(async (resolve, reject) => {
   eachLimit((await getAsyncArray), 500, (item, callback) => {
     // do other things that use native promises.
   }, (error) => {
     if (error) return reject(error);
     // resolve here passing the next value.
   });
 });
}

見ての通り、このままでは myFunction の2番目のコールバック内の値にアクセスできないので、非同期関数として使用します。 eachLimit 関数を使用します。

どのように解決するのですか?

プロミスコンストラクタ・エグゼキュータ関数の内部で効率的にプロミスを使用しているので、この プロミスコンストラクタのアンチパターン .

あなたのコードは、主なリスクである「すべてのエラーを安全に伝搬させない」ことの良い例です。理由を読む そこで .

を使用し、さらに async / await は、同じトラップでもさらに驚きを与えることができます。比べてみてください。

let p = new Promise(resolve => {
  ""(); // TypeError
  resolve();
});

(async () => {
  await p;
})().catch(e => console.log("Caught: " + e)); // Catches it.

素朴な(間違った)気持ちで async と同等です。

let p = new Promise(async resolve => {
  ""(); // TypeError
  resolve();
});

(async () => {
  await p;
})().catch(e => console.log("Caught: " + e)); // Doesn't catch it!

最後の1つはブラウザのウェブコンソールを見てください。

最初のものは、任意の 即時 例外が発生した場合,新たに構築されたプロミスは拒否されます(ただし,プロミスコンストラクタの実行関数内の .then は自己責任でお願いします)。

2つ目の方法はうまくいきません。 async 関数は によって返される暗黙の約束です。 async 関数自体 .

プロミスコンストラクタの実行関数の戻り値は未使用なので、これは悪いニュースです!プロミスコンストラクタの実行関数の戻り値は未使用なので、これは悪いニュースです。

あなたのコード

を定義できない理由はない。 myFunction として async :

async function myFunction() {
  let array = await getAsyncArray();
  return new Promise((resolve, reject) => {
    eachLimit(array, 500, (item, callback) => {
      // do other things that use native promises.
    }, error => {
      if (error) return reject(error);
      // resolve here passing the next value.
    });
  });
}

とはいえ、せっかく await ?