Async/Await 未按预期使用 for 循环语句

Async/Await is not working as expected with for loop statement

我是 Javascript 和 nodejs 的新手。在尝试了解承诺和回调的工作原理时,我尝试在 'for' 循环中调用一个函数,如下所示。我试图实现的是使用承诺每 2 秒打印一次 'i' 值。但是,程序等待2秒,打印3次i值后退出。

for(let i = 0; i < 3 ; i++){
    func(callback,i);
}

async function func(callback,i){
   await callback(i);
}
function callback(i){
    return new Promise((res,rej) =>{
        setTimeout(()=>{
            console.log('i = ',i)
            res();
        }, 2000);

    })
}

谁能帮我理解为什么会这样?

这里有一些函数可以帮助您了解 promises 如何与数组一起工作,我们会在这些地方犯常见的错误。

function promiseFunction(v) {
    return new Promise((resolve) => {
        setTimeout(() => resolve(v), 1000);
    });
}
function f1() {
    [1, 2, 3, 4]. forEach(async(i) => {
        const v = await promiseFunction(i);
        console.log(`-f1 v- ${v}<br/>`);
    });
    console.log('all done<br/>');
}
async function f2() {
    await Promise.all([1, 2, 3, 4].map(async(i) => {
        const v = await promiseFunction(i);
        console.log(`-f2 v- ${v}<br/>`);
    }));
    console.log('all done<br/>');
}
async function f3() {
    await [1, 2, 3, 4].reduce((p, i) => {
        return p.then(async () => {
            const v = await promiseFunction(i);
            console.log(`-f3 v- ${v}<br/>`);
        });
    }, Promise.resolve());
    console.log('all done<br/>');
}

async function func() {
   console.log('f1');
   await f1();
   console.log('f2');
   await f2();
   console.log('f3');
   await f3();
}

func();

f1() 将首先打印 all done,然后在一秒后立即打印 1,2,3,4。
f2() 将在一秒后立即打印 1,2,3,4 然后打印 all done.
f3() 将每秒打印 1,2,3,4,然后打印 all done.

你的异步函数 func 也是 returns 一个承诺,所以你需要在调用之前使用 await 关键字。

for(let i = 0; i < 3 ; i++){
    await func(callback,i);
}

你可以用 async 立即执行的函数包装你的循环并在其中添加 await (正如这里已经建议的那样):

(async () => {
  for(let i = 0; i < 3 ; i++){
    await callback(i);
  }
})();

function callback(i){
  return new Promise((res,rej) =>{
    setTimeout(()=>{
      console.log('i = ',i)
      res();
    }, 2000);
  })
}

这是我在 Bergi 编辑之前的原始答案:

(async () => {
  for(let i = 0; i < 3 ; i++){
    await func(callback,i);
  }
})()

async function func(callback,i){
  await callback(i);
}

function callback(i){
  return new Promise((res,rej) =>{
    setTimeout(()=>{
      console.log('i = ',i)
      res();
    }, 2000);
  })
}

您需要等待异步函数完成

for(let i = 0; i < 3 ; i++){
    await func(callback,i);
}

但是由于您不能在全局范围内使用 await 关键字,因此您需要将 for 循环包装在异步函数中,然后调用它

async function myTest(){
    for(let i = 0; i < 3 ; i++){
        await func(callback,i);
    }
}
myTest()

你很接近。缺少的信息是 async 函数(你的 func())隐含地 returns 一个 AsyncFunction 对象,它隐含地 returns Promise 本身(doc)。

您使用 immediately invoked function expression 的代码将是

(async () => {
    for(let i = 0; i < 3 ; i++){
        await func(callback,i);
    }
})()

async function func(callback,i){
   await callback(i);
}
function callback(i){
    return new Promise((res,rej) =>{
        setTimeout(()=>{
            console.log('i = ',i)
            res();
        }, 2000);
    })
}

请注意,现在在大多数浏览器中原生可用的构造 for await..of (doc)。你也可以试试这个。