我知道以前可能有人问过这个问题,但在过去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数是多少?
我已经接触过bluebird
和util
节点库之类的东西,但仍然有点困惑。我认为这个异步逻辑非常强大,尽管我无法真正掌握它。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文档在这里覆盖了他们的循环(我认为它有点过时,但主体没有改变(。