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

2020/10/17 05:41 · javascript ·  · 0评论

我一直在浏览async/阅读await了几篇文章之后,我决定自己测试一下。但是,我似乎无法解决为什么它不起作用的问题:

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):

>外部:[对象承诺]

>内部:嘿

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

有没有办法可以使用函数内部返回的值而不使用.then()after main()

我似乎无法绕开为什么这行不通的想法。

因为main回报承诺;所有async功能都可以。

在顶层,您必须:

  1. 使用async永远不会拒绝的顶级函数(除非您希望出现“未处理的拒绝”错误),或者

  2. 使用thencatch,或

  3. (即将推出!)使用顶层await,该提案已进入允许在模块中顶层使用过程中的第3阶段await

#1-async永不拒绝的顶级功能

(async () => {
    try {
        var text = await main();
        console.log(text);
    } catch (e) {
        // Deal with the fact the chain failed
    }
})();

注意catch; 必须处理Promise拒绝/异步异常,因为没有其他事情要做;您没有呼叫者将其传递给。如果愿意,可以在通过catch函数(而不是try/catch语法)调用它的结果上执行此操作

(async () => {
    var text = await main();
    console.log(text);
})().catch(e => {
    // Deal with the fact the chain failed
});

...更加简洁(出于这个原因,我喜欢它)。

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

#2-thencatch

main()
    .then(text => {
        console.log(text);
    })
    .catch(err => {
        // Deal with the fact the chain failed
    });

catch如果发生在链中或在你的错误处理程序将调用then处理程序。(请确保您的catch处理程序不会抛出错误,因为没有任何内容可以处理。)

或两个参数then

main().then(
    text => {
        console.log(text);
    },
    err => {
        // Deal with the fact the chain failed
    }
);

再次注意,我们正在注册一个拒绝处理程序。但是,以这种形式,请确保您的then回调都不会引发任何错误,也没有任何内容可以处理。

#3顶级await模块

您不能await在非模块脚本的顶层使用await,但是顶层建议第3阶段)允许您在模块的顶层使用它。这与使用顶级async函数包装器(上面的#1)相似,因为您不希望您的顶级代码拒绝(抛出错误),因为这将导致未处理的拒绝错误。因此,除非您要在出现问题时(例如#1)遇到未处理的拒绝,否则您要将代码包装在错误处理程序中:

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

请注意,如果执行此操作,则从模块导入的任何模块都将等待,直到您履行的诺言await得以兑现await评估使用顶层的模块时,它基本上会向模块加载器返回一个承诺(就像async函数一样),该加载器会等到该承诺得到解决,然后再评估依赖于该模块的任何模块的主体。

顶层await已进入第3阶段,因此您问题的答案如何在顶层使用async / await?就是将await通话添加main()

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

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

要不就:

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

请记住,它仍然仅在Webpack@v5.0.0-alpha.15中可用

如果您使用的是TypeScript,它将降落在3.8版中

v8增加了对模块的支持

它也通过支持杰诺(由贡萨洛- bahamondez评论)。

解决此问题的实际方法是采用不同的方法。

您的目标可能是某种初始化,通常发生在应用程序的顶层。

解决方案是确保应用程序的顶层只有一个JavaScript语句。如果您的应用程序顶部只有一条语句,那么您可以在其他任何地方随意使用async / await(当然要遵循常规语法规则)

换句话说,将整个顶层包装在一个函数中,使其不再是顶层,并且解决了如何在应用程序的顶层运行异步/等待的问题,而您却没有。

这是应用程序的顶层外观:

import {application} from './server'

application();

在当前答案的基础上提供更多信息:

node.js当前,文件的内容以类似字符串的方式连接起来以形成函数体。

例如,如果您有一个文件test.js

// Amazing test file!
console.log('Test!');

然后node.js将秘密连接一个看起来像这样的函数:

function(require, __dirname, ... a bunch more top-level properties) {
  // Amazing test file!
  console.log('test!');
}

需要注意的主要事情是,结果函数不是异步函数。因此,您不能await在其内部直接使用该术语

但是说您需要使用此文件中的promise,那么有两种可能的方法:

  1. 不要在函数内部await 直接使用
  2. 不要使用 await

选项1要求我们创建一个新范围(该范围可以是async,因为我们可以控制它):

// Amazing test file!
// Create a new async function (a new scope) and immediately call it!
(async () => {
  await new Promise(...);
  console.log('Test!');
})();

选项2要求我们使用面向对象的Promise API(使用Promise的方法不太漂亮,但功能相同)

// Amazing test file!
// Create some sort of promise...
let myPromise = new Promise(...);

// Now use the object-oriented API
myPromise.then(() => console.log('Test!'));

我个人希望,如果可行,node.js默认会将代码连接成一个async函数。这样可以摆脱这种头痛。

You can now use top level await in Node v14.3.0

import axios from "axios";

const { data } = await axios.get("https://api.namefake.com/");
console.log(data);

run it with --harmony-top-level-await flag

node --harmony-top-level-await index.js

Top-level await is a feature of the upcoming EcmaScript standard. Currently, you can start using it with TypeScript 3.8 (in RC version at this time).

How to Install TypeScript 3.8

You can start using TypeScript 3.8 by installing it from npm using the following command:

$ npm install typescript@rc

At this time, you need to add the rc tag to install the latest typescript 3.8 version.

节点-

您可以
node --experimental-repl-await在REPL中运行我不太了解脚本。

Deno -

Deno已经内置。

由于main()异步运行,因此会返回一个承诺。您必须在then()方法中获得结果并且因为then()返回承诺也是如此,所以您必须调用process.exit()以结束程序。

main()
   .then(
      (text) => { console.log('outside: ' + text) },
      (err)  => { console.log(err) }
   )
   .then(() => { process.exit() } )
本文地址:http://javascript.askforanswer.com/ruhezaidingcengshiyongyibu-dengdai.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!