【问题标题】:using await on global scope without async keyword在没有 async 关键字的全局范围内使用 await
【发布时间】:2019-01-02 15:31:41
【问题描述】:

我正在尝试在 nodejs REPL 中的 全局范围 上做类似的事情。根据我的理解,以下两个陈述都是有效的。 see docs

let x = await Promise.resolve(2);
let y = await 2;

但是,这两个语句都引发了错误。

有人可以解释为什么吗? 我的节点版本是 v8.9.4

【问题讨论】:

  • 为什么?因为这就是 async/await 的设计方式。如果您想了解为什么要这样设计,它会很复杂,但这与 Javascript 的单线程事件驱动性质以及它们在引擎的一个主要版本中可以吸收多少变化有关。而且,假设模块是同步加载的,顶级await 会导致该假设出现各种问题。将你自己的 async 包装器放在你想使用 await 的东西上。
  • 您不会,或者您等待top-level async 引起一系列问题。
  • 您可以编写自己的 REPL 来包装 AIiFE 中输入的所有代码。

标签: javascript node.js ecmascript-6 es6-promise


【解决方案1】:

更新

使用Node时,文件当前必须具有.mjs 扩展名才能工作。

顶级awaits 可以在浏览器模块中使用。使用时,脚本标签必须包含type 属性,该属性必须设置为module

<script src="/script.js" type="module"></script>
const start = Date.now()

console.log('Pre call.')
await delayedCall()
console.log('Duration:', Date.now() - start)

function delayedCall() {
  return new Promise(resolve => setTimeout(() => resolve(), 2000))
}

旧答案

await 只能在标记为async 的函数中使用,因此有两种方法可以解决此问题。

注意: 有一个提案可能最终允许使用Top level await 调用。

第一种方法是像这样创建一个自调用函数:

(async function() {
  let x = await Promise.resolve(2)
  let y = await 2
  
  console.log(x, y)
})()

或者第二种方式是使用.then()

Promise.resolve(2).then(async data => {
  let x = data
  let y = await 2

  console.log(x, y)
})

【讨论】:

  • 您的第二个代码块非常混乱。 await 放错地方了,=&gt; 之间不能有空格。 await 2 毫无意义。
  • 好吧,IMO 好的答案不会重复错误的代码,他们会更正并解释原因。
  • 另外,在更高的范围内分配给xy 是不好的。这通常表明有人想尝试在更高范围内使用这些变量,并且通常不会起作用,因为设置它们的时间。如果我是你,我会删除你的第二个代码示例。这不是一个人应该做的事情。
  • 我知道您必须在异步函数中使用 await。我不明白为什么他们不能让全局上下文就像在异步函数中执行一样。将节省人们不得不编写像这样丑陋的样板包装。
  • 顶级 await 目前在 node.js v13.3+ 中位于 --harmony-top-level-await 标志后面,但它只能在模块中使用(扩展名为 *.mjs*.js 的文件)附带 package.json 设置 "type": "module"),来源见 this answer
【解决方案2】:

Node.js 13.3 或更高版本支持Top-level-await

例子:

await Promise.resolve(console.log('?')); // → ?

(虽然问题是关于 REPL,关于作为脚本文件运行的说明。设置 {"type": "module"}package.json 或使用文件扩展名 .mjs

【讨论】:

    【解决方案3】:
    async function getTen() {
      return 10;
    }
    
    (async () => {
      let ten = await getTen();
      console.log(ten);
    })();
    

    来源:https://javascript.plainenglish.io/5-javascript-interview-questions-to-identify-outstanding-developers-859a71c3d7f

    【讨论】:

      【解决方案4】:

      此提案目前处于 TC39 流程的第 3 阶段。 LINK

      您现在可以在 Google Chrome 和 Mozilla Firefox 中使用此功能。您可以在控制台中使用没有异步的顶级等待。

      https://twitter.com/addyosmani/status/1080365576218759168

      【讨论】:

        【解决方案5】:

        您可以将全局范围内的所有代码包装在异步函数中。

        例如:

        // ...global imports...
        
        new Promise (async () => {
        
          // ...all code in the global scope...
        
        }).then()
        

        【讨论】:

        • gregn3,问题的目的不是使用.then().catch() 的承诺链
        • @nmxl 你没有在你的问题中提到这一点。
        • 至少不为零:)
        【解决方案6】:

        从节点 10 开始,您可以使用 --experimental-repl-await 运行节点进程以允许等待级别 https://nodejs.org/api/repl.html#repl_await_keyword

        【讨论】:

          【解决方案7】:

          你不能那样做。 MDN doc

          await 运算符用于等待 Promise。 只能使用 在异步函数中。

          【讨论】:

            猜你喜欢
            • 2022-01-10
            • 2018-10-29
            • 2021-09-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-04
            • 1970-01-01
            • 1970-01-01
            • 2012-04-29
            相关资源
            最近更新 更多