迪诺顶级等待

时间:2020-05-20 15:23:50

标签: javascript async-await 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 (const req of s) {
  req.respond({ body: "Hello World\n" });
}

这种语法是什么?

它是特定于deno的,还是在this tc39提案中找到的顶层等待项?

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

2 个答案:

答案 0 :(得分:8)

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

是专用于deno还是在此tc39中找到的顶级等待项 提案?

否,它不是特定于Deno,而是different proposaltop-level await


这是asyncIterator的一个简单示例,该示例也可以在浏览器中使用(非专用)

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

答案 1 :(得分:1)

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

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

我首先建议您抽出一些时间阅读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 中的;

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