web-dev-qa-db-ja.com

Await Asyncを使用したwhileループ。

このJavaScript関数は、whileループを非同期に使用しているようです。非同期条件でwhileループを使用する正しい方法ですか?

 var Boo;
 var Foo = await getBar(i)
 while(Foo) {
    Boo = await getBar3(i)
    if (Boo) {
      // something
    }
    Foo = await getBar(i)
    i++
  }

私が思うことはこれです:

var Boo;
var Foo;
getBar(i).then( (a) => {
  Foo = a;
  if(Foo) {
    getBar3(i).then( (a) => {
      Boo = a
      if(Boo) {
        //something
        i++;
        getBar(i).then( (a} => { Repeat itself...} 
      }
   }
  }
})

それが完全に偽の場合、非同期await + whileループでそれを行う別の方法を示すことができますか?

ありがとう!!

19
Hcharlanes

非同期条件でwhileループを使用する正しい方法ですか?

はい。 async functionsは、それぞれのpromiseが満たされるまでawaitごとに実行を一時停止し、すべての制御構造は以前と同様に機能し続けます。

18
Bergi

うん、それはこのようにして大丈夫です:

    let stopped = false

    // infinite loop
    while(!stopped) {
       let res = await fetch('api link') 
       if (res.something) stopped = true // stop when you want
    }
3
RTW

この質問が出されてからしばらく経ちました。私は長年の他の言語(パンチカードや紙テープで始まる)の後でjsを始めて、この問題を解決する必要がありました。これが私の答えです:

var loopContinue = true;
var n = 0;

async function  Managework() {
  while (loopContinue) {  //seemingly an infinite loop
    //await (doWork(n));
    await (doWork(n).catch(() => { loopContinue=false; }));
    n++;
    console.log(`loop counter ${n}`);
  }
  console.log(`loop exit n=${n} loopContinue=${loopContinue}`);
 }

Managework();

function doWork(n) {
 return new Promise((resolve, reject) => {
    console.log(`dowork(${n})`);
    if (n > 5) {
      //loopContinue = false;
      reject(`done`);
    }
    setTimeout(() => {
      resolve('ok');
    }, 1000);
  });
}

必要に応じて、ループは5番目の反復後に中断します。 'loopContinue'グローバルは、仕事関数またはプロミスのキャッチ(または当時)に設定できます。 thenまたはcatchで 'break'を使用するだけで疲れましたが、エラーが発生します。

DoWorkで実行する場合は、キャッチを削除してdoWork()を呼び出し、doWorkの// loopContinue = falseのコメントを外します。どちらの方法でも機能します。これはnode.jsでテストされました

NextTickで何かを見つけましたが、これははるかに簡単に思えます。

0
Charles Bisbee

はい。最初の例は、非同期条件でwhileループを使用する良い方法ですgetBarおよびgetBar3は非同期関数です(非同期としてマークされるか、単にPromiseを返します)。

もちろん実行は非同期コンテキスト内async関数内)である必要があります

私が見ることができる可能な問題は、最初にgetBarが2回実行され、同じiと残りの実行では、iwhileの間で一致しないifを使用します。 これが望ましい動作でない場合おそらくより正しいバージョンは次のようになります:

    (async ()=>{
     while(await getBar(i)) {    
        if (await getBar3(i)) {
          //do something
        }
        i++;
      }
    })();

偽の例を見る here

0
Marinos An