试图理解节点中的async/await/sync



我知道以前可能有人问过这个问题,但在过去20年的单线程语言中,我真的很难理解node的真实性质。相信我,我已经读了很多SO的帖子,github的讨论,以及关于这方面的文章。

我想我知道每个函数都有自己的线程类型的处理。然而,在某些情况下,我希望我的代码是完全同步的(一个接一个地启动一个函数(。

例如,我制作了3个函数,这些函数似乎向我展示了节点的异步i/o是如何工作的:

function sleepA() {
setTimeout(() => {
console.log('sleep A')
}, 3000)
}
function sleepB() {
setTimeout(() => {
console.log('sleep B')
}, 2000)
}
function sleepC() {
setTimeout(() => {
console.log('sleep C')
}, 1000)
}
sleepA()
sleepB()
sleepC()

它输出以下内容:

sleep C
sleep B
sleep A

好的,这很有道理。节点同时启动所有功能,首先完成的功能将被记录到控制台。有点像看赛马。节点开火,功能启动,最快的一个获胜。

那么现在我该如何使这些同步,以便顺序始终是A、B、C,而不管setTimeout数是多少?

我已经接触过bluebirdutil节点库之类的东西,但仍然有点困惑。我认为这个异步逻辑非常强大,尽管我无法真正掌握它。php已经摧毁了我的思想。

我该如何使这些同步,以便订单始终为A、B、C

您已经确认,您的意思是,在A完成之前,您不想启动B的超时(等等(。

在2021年,最简单的方法是为setTimeout使用一个启用承诺的包装器,比如这个:

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

然后,使sleepA和这样的async函数:

async function sleepA() {
await delay(3000);
console.log("sleep A");
}
async function sleepB() {
await delay(2000);
console.log("sleep B");
}
async function sleepC() {
await delay(1000);
console.log("sleep C");
}

然后,您的代码可以await这些函数中的每一个返回的promise,这将阻止代码继续运行,直到promise得到解决:

await sleepA();
await sleepB();
await sleepC();

您可以在async函数内部或(在Node.js的现代版本中(在模块的顶层执行此操作。您不能在同步函数中使用await,因为await本质上是异步的。

我想我理解每个函数都有自己的线程类型的交易

不,JavaScript函数与其他同步语言的函数一样(尽管JavaScript享有盛誉,但它本身绝大多数是同步的;它只是在高度异步的环境中使用,最近还获得了一些使其更容易实现的功能(。下面将对此进行详细介绍。

好的,所以这是有道理的。节点同时启动所有功能,首先完成的功能将被记录到控制台。有点像看赛马。节点开火,功能启动,最快的一个获胜。

关闭。函数按顺序运行,但每个函数所做的只是设置一个计时器并返回。他们不会等计时器启动。稍后,当它触发时,它会调用您传递到setTimeout中的回调。

JavaScript有一个主线程,所有东西都在该主线程上运行,除非您明确地让它在工作线程或子进程中运行。Node.js是高度异步的(与web浏览器一样,另一个地方主要使用JavaScript(,但默认情况下,您的JavaScript代码都在一个线程上运行。有一个循环处理";工作"作业按事件(如计时器启动(排队,然后由事件循环按顺序处理。我在这里做了更多的介绍,Node.js文档在这里覆盖了他们的循环(我认为它有点过时,但主体没有改变(

最新更新