【问题标题】:Deno top level awaitDeno 顶层等待
【发布时间】:2021-02-14 14:48:26
【问题描述】:

正在阅读 deno 新 JS 运行时的homepage

我看到了以下代码:

import { serve } from "https://deno.land/std@0.50.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}

我从未见过以下语法(for await):

for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}

这种语法是什么?

它是 deno 特有的,还是 thistc39 提案中的顶级等待?

编辑:为什么它可以在async 函数的外部使用?

【问题讨论】:

标签: javascript async-await deno


【解决方案1】:

for await...of 语句用于遍历异步迭代器,serve 返回一个异步迭代器,其中每次迭代都是一个新的传入请求。

是 deno 特有的还是在这个 tc39 中发现的顶级等待 提案?

不,它不是 Deno 特有的,它是 different proposal 而不是 top-level await


这是一个简单的 asyncIterator 示例,它也适用于浏览器(非 deno 专有)

const obj = {
   async *[Symbol.asyncIterator]() {
      for(let i = 0; i < 10; i++)
        yield new Promise(resolve => setTimeout(() => resolve(i), 100));
   }
};

(async() => {
  // You don't need the wrapper if the environment 
  // supports top-level await, e.g: Deno
  for await(const i of obj)
    console.log(`${i}`, new Date())

})();

编辑:为什么它可以在异步函数之外使用?

因为 Deno 支持top-level await

【讨论】:

  • 顺便说一句,一个有趣的补充是代码是在示例中的 aync 函数之外运行的
  • 不客气。我添加了一个示例,您可以查看它是如何构建的。
  • 大多数浏览器不支持顶级等待,我将它包装在异步函数中的原因。但这是证明它不是 top-levelawait 的一部分的完美示例
  • 我认为“serve 返回一个异步迭代器”部分不正确。它返回一个异步可迭代对象,并且只有一次像s[Symbol.asyncIterator]() 这样调用时,您才会收到一个异步迭代器。 for await 隐藏了所有这些内部工作。
【解决方案2】:

当我决定使用 Deno 时,这也引起了我的注意。我喜欢 Deno,因为它在 ES6 上是原生的,比如 Promises、Import - Export,而且你甚至不需要像 Node 中那样的 npm,只需 import 来自 url 的包。

现在这个asyncawait 抽象是为了简化代码,但它也隐藏了很多东西,有些人基本上很难理解到底发生了什么。

我首先建议您花点时间阅读this beautiful article on asychronous iteration

问题是,在启动服务器的非常基本的代码中

import { serve } from "https://deno.land/std@0.87.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://127.0.0.1:8000/");

for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}

您必须接受由于某种原因for await 循环在收到请求时转了一次。实际上,这正是它的作用。驱动异步迭代和承诺的机器是隐藏的。

现在我们应该知道s in;

const s = serve({ port: 8000 });

实际上是一个异步可迭代对象。所以它有一个叫做[Symbol.asyncIterator]的方法。当你像s[Symbol.asyncIterator]() 一样调用它时,你会得到一个带有next 方法的异步迭代器对象。通常在调用 next() 时使用同步迭代器会收到像 {value: "stg", done: false} 这样的对象,但在异步迭代器中会收到 Promise。这个承诺,一旦收到请求时解决(或者如果发生错误则拒绝)给我们一个类似

的对象
{ value: ServerRequest Object 
, done : false
}

所以上面的代码也可以写成这样;

import { serve } from "https://deno.land/std@0.87.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://127.0.0.1:8000/");

var rqs = s[Symbol.asyncIterator](),
    srv = (app,rqs) => rqs.next().then(rq => (app(rq.value), srv(app,rqs))),
    app = req => req.respond({body: "Hello World\n"});

srv(app,rqs); // receive requests and handle them with your app

【讨论】:

    猜你喜欢
    • 2021-07-16
    • 2022-12-19
    • 1970-01-01
    • 2020-08-26
    • 2022-09-28
    • 2021-03-26
    • 1970-01-01
    • 1970-01-01
    • 2021-02-13
    相关资源
    最近更新 更多