如何在顶层使用异步/等待?兼容性

我一直在研究/在阅读了几篇文章之后,我决定自己测试一下。但是,我似乎无法理解为什么这不起作用:asyncawait

async function main() {  
    var value = await Promise.resolve('Hey there');
    console.log('inside: ' + value);
    return value;
}

var text = main();  
console.log('outside: ' + text);

控制台输出以下内容(节点 v8.6.0):

>外:[对象承诺]

里面>:嘿,那里

为什么函数内的日志消息在之后执行?我认为创建 /的原因是为了使用异步任务执行同步执行。asyncawait

有没有办法在不使用 after 的情况下使用函数内返回的值?.then()main()


答案 1

我似乎无法理解为什么这不起作用。

因为回报了一个承诺;所有功能都可以。mainasync

在顶层,您必须:

  1. 使用顶级等待提案MDN;ES2022,在现代环境中得到广泛支持),允许在模块中顶级使用。await

  2. 使用从不拒绝的顶级函数(除非您想要“未处理的拒绝”错误)。async

  3. 使用和 。thencatch

模块中的 #1 顶级await

您可以在模块的顶层使用。在你确定的承诺之前,你的模块不会完成加载(这意味着任何等待你的模块加载的模块在承诺确定之前都不会完成加载)。如果承诺被拒绝,您的模块将无法加载。通常,顶级用于以下情况:您的模块在承诺确定之前无法完成其工作,除非实现承诺,否则根本无法完成,所以这很好:awaitawaitawait

const text = await main();
console.log(text);

如果即使承诺被拒绝,您的模块也可以继续工作,则可以将顶层包装在 /:awaittrycatch

// In a module, once the top-level `await` proposal lands
try {
    const text = await main();
    console.log(text);
} catch (e) {
    // Deal with the fact the chain failed
}
// `text` is not available here

当使用顶级的模块被评估时,它会向模块加载程序返回一个 promise(就像函数一样),该 promise 会等到该 promise 被结算,然后再评估依赖于它的任何模块的主体。awaitasync

不能在非模块脚本的顶层使用,只能在模块中使用。await

#2 - 从不拒绝的顶级功能async

(async () => {
    try {
        const text = await main();
        console.log(text);
    } catch (e) {
        // Deal with the fact the chain failed
    }
    // `text` is not available here
})();
// `text` is not available here, either, and code here is reached before the promise settles
// and before the code after `await` in the main function above runs

请注意 ;您必须处理承诺拒绝/异步异常,因为没有其他事情会发生;你没有调用者可以将它们传递给(与上面的#1不同,其中你的“调用者”是模块加载器)。如果您愿意,可以根据通过函数(而不是/语法)调用它的结果来执行此操作:catchcatchtrycatch

(async () => {
    const text = await main();
    console.log(text);
})().catch(e => {
    // Deal with the fact the chain failed
});
// `text` is not available here, and code here is reached before the promise settles
// and before the code after `await` in the main function above runs

...这有点简洁,尽管它有点混合了模型(/和显式承诺回调),否则我通常会建议不要这样做。asyncawait

或者,当然,不要处理错误,而只允许“未处理的拒绝”错误。

#3 - 和thencatch

main()
    .then(text => {
        console.log(text);
    })
    .catch(err => {
        // Deal with the fact the chain failed
    });
// `text` is not available here, and code here is reached before the promise settles
// and the handlers above run

如果链或处理程序中发生错误,将调用处理程序。(请确保您的处理程序不会引发错误,因为没有注册任何内容来处理它们。catchthencatch

或者两个参数都指向:then

main().then(
    text => {
        console.log(text);
    },
    err => {
        // Deal with the fact the chain failed
    }
);
// `text` is not available here, and code here is reached before the promise settles
// and the handlers above run

再次注意,我们正在注册拒绝处理程序。但在此表单中,请确保两个回调都不会引发任何错误,因为不会注册任何内容来处理它们。then


答案 2

顶级 await 已移至第 3 阶段,因此您的问题的答案如何在顶层使用 async/await? 只需使用 :await

const text = await Promise.resolve('Hey there');
console.log('outside: ' + text)

如果你想要一个函数:添加到调用:main()awaitmain()

async function main() {
    var value = await Promise.resolve('Hey there');
    console.log('inside: ' + value);
    return value;
}

var text = await main();  
console.log('outside: ' + text)

兼容性