在 for 循环中努力等待

时间:2021-06-02 07:11:30

标签: javascript node.js async-await

我现在有这个功能

async function checkEntry(results: any) {
    let ind = 0;
    for (let i = 0; i < results.length; i++) {
        const e = results[i];

        await checkStuff(e); // returns void
        await checkOtherStuff(e); //returns void 
        await updateStatus(e); //returns void aswell

        ind++;
        await sleep(1);
    }
}

现在我想这将按此顺序执行 checkStuff、checkOtherStuff、updateStatus,然后进入 for 循环的下一次迭代。

相反,它堆积了 checkStuff 的承诺,并且在循环完成后(控制台记录了 10,000 个,共 10,000 个)它仍然给我调用了一段时间的第一个函数的结果。

为什么这个函数没有按照我想要的顺序运行?或者更确切地说,为什么 await 关键字不会在完成调用所需的时间内阻止循环的执行?

编辑:checkStuff 函数的内容:

async function checkStuff(result: any) {
    
    try {
        const req = await https.get(result.url, async (res) => {
            if(res.statusCode == 404) console.log(result.url+' returns 404');
        });
        req.on("error", (e) => {
            // console.error(e);
        });
    } catch (err) {
        // console.error(err);
    }
}

2 个答案:

答案 0 :(得分:2)

如果您使用 await 关键字,则需要在承诺中使用它。

目前 checkStuff 没有返回承诺,因此您可以调整代码以在执行回调时解决承诺。

const https = require('https');

function checkStuff(result) {
    return new Promise((resolve, reject) => {
        const req = https.get(result.url, (res) => {
            if (res.statusCode == 404) {
                console.log(result.url + ' returns 404');
                reject(res);
            } else {
                resolve(res);
            }
        });

        req.on('error', (e) => {
            console.error(e);
            reject(e);
        });
    }).catch((e) => {
        console.log(e);
    });
}

回调和承诺是不同的。

当一个方法接受回调时,它会说,当我完成这个任务时,我会调用你选择的函数。

当你使用 Promise 时,你创建了一个 Promise 对象并返回它。它将保持“待定”状态,直到承诺中的某些内容调用解决或拒绝。您可以像这样 resolve(data) 将结果传递给解决或拒绝。

现在通过将这个 promise 分配给 async 函数内的一个变量,您已经解锁了 await 关键字。 await 将阻止您的代码移动到下一行,直到 promise 得到解决,因此这有助于您使代码同步。

async function main() {
    const result = await checkStuff();
    /* 
       Result is now a Promise object in the pending state. 
       The code will not continue past the previous line 
       until the result variable changes from pending to resolved.
    */
    
    console.log(result);
}

答案 1 :(得分:1)

https.get 不提供承诺接口,await 不会神奇地让您的代码等待异步任务完成。

它是合成糖,可以更轻松地使用 Promise 并且需要 Promise 才能工作。

如果像 https.get 这样的函数不提供 Promise 接口,那么您需要以某种方式将其转换为 Promise,例如用 new Promise((resolve, reject) => …) 包裹它。

const req = await new Promise((resolve, reject) => {
  https.get(result.url, async (res) => {
    if(res.statusCode == 404) console.log(result.url+' returns 404');
    resolve()
  });
  req.on("error", (e) => {
    reject(e)
  });
})