While 循环使用 Await Async.

问题描述 投票:0回答:7

这个 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...} 
      }
   }
  }
})

如果那是完全错误的,你能展示另一种使用异步等待 + while 循环的方法吗?

谢谢!!

loops asynchronous while-loop async-await ecmascript-next
7个回答
39
投票

在异步条件下使用 while 循环是正确的方法吗?

是的。

async function
s 只是在每个
await
暂停执行,直到各自的承诺履行,并且任何控制结构继续像以前一样工作。


33
投票

是的,这样做很好:

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

13
投票

在异步条件下使用 while 循环是正确的方法吗?

前提是

getBar
getBar3
是异步函数
(标记为async或者只是返回一个
Promise
)。

当然执行应该在异步上下文中(在

async
函数中)

一个可能的issue,我可以看到,最初有 2 次执行

getBar
具有相同的
i
,其余执行使用
i
while
之间不匹配的
if
如果这不是期望的行为也许更正确的版本是:

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

看一个模拟的例子在这里


2
投票

一个简单的方法是:

// returns a delayed promise 
const delay = ms => new Promise(resolve => setTimeout(resolve, ms))

// performs a specific (mathematical) operation every "ms" (milliseconds)
const dec = async (i, ms) => (await delay(ms), --i)

const foo = async () => {
  let i = 5;
  
  // runs an async operation which decreases "i" by 1 every 500ms
  while(i = await dec(i, 500)) 
    // prints 4, 3, 2, 1 with a delay 
    console.log(i) 
}

foo()

这是我的GIST如果你需要给它加星标以备后用。

或者,你可以数:

// returns a delayed promise 
const delay = ms => new Promise(resolve => setTimeout(resolve, ms))

// performs a specific (mathematical) operation every "ms" (miliseconds)
const inc = async (i, ms) => (await delay(ms), ++i)

const foo = async () => {
  let i = 0;
  
  // runs an async operation which increases "i" by 1 every 500ms
  while((i = await inc(i, 500)) < 5) {
    // prints 1,2,3,4 with a delay 
    console.log(i) 
  }
}

foo()


0
投票

基于这个例子,我们看到在

await
循环中使用
while
会触发SYNCHRONOUS代码执行。换句话说,在循环的一次迭代完成之前,不会开始第二次循环

let counter = 0;

const promise = () =>
  new Promise((resolve, reject) =>
    setTimeout(() => {
      resolve(1);
    }, 2000)
  );

(async() => {
  console.log("Start")
  console.time('allTime');
  while (counter < 3) {
    await promise();
    console.log('Resolve promise', counter);
    counter++;
  }
  console.timeEnd('allTime');
})();


0
投票

由于

while
循环体同步工作,我们需要将代码移出循环体。
此解决方案可能会帮助某人:

while(await (async () => {
  Boo = await getBar3(i)
  if (Boo) {
    // something
  }
  Foo = await getBar(i)
  i++
  return Foo; // you must return the condition that the loop depends on it
})()); // Adding this semicolon is crucial

-1
投票

问这个问题已经有一段时间了。在使用其他语言多年(从穿孔卡和纸带开始)之后,我是 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' global 可以在 work 函数中设置,也可以在 promise 的 catch(或者可以是 then)中设置。我厌倦了在 then 或 catch 中使用“break”,但出现错误。

如果你想在 doWork 中这样做,你可以消除 catch 并调用 doWork() 并取消注释 doWork 中的 // loopContinue= false。无论哪种方式都有效。这是用 node.js 测试的

我在 nextTick 上找到了东西,但这似乎容易多了。

© www.soinside.com 2019 - 2024. All rights reserved.