web-dev-qa-db-ja.com

新しいPromise()コンストラクター内でasync / awaitを使用するのはアンチパターンですか?

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関数を非同期として宣言できません。

46
user5487299

Promiseコンストラクターエグゼキューター関数内でpromiseを効果的に使用しているため、これは Promise constructor anti-pattern です。

あなたのコードは、すべてのエラーを安全に伝播しないという主なリスクの良い例です。理由をお読みください あり

さらに、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!

ブラウザのWebコンソールで最後のWebコンソールを探します。

Promiseコンストラクターエグゼキューター関数のすべてのimmediate例外は、新しく作成されたプロミスを便利に拒否するため(ただし、.then自分で)。

async関数の即時例外は、async関数自体によって返される暗黙のプロミスを拒否するため、2番目の関数は機能しません

Promiseコンストラクターexecutor関数の戻り値は使用されないため、これは悪いニュースです!

あなたのコード

myFunctionasyncとして定義できない理由はありません。

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があるのに、なぜ古くなった同時実行制御ライブラリを使用するのですか?

36
jib