我正在尝试在nodejs中自学异步编程,我编写这个程序是为了更好地理解异步编程。
async function t(){
for(let b = 0 ;b < 9000000000; b++){
}
console.log("Hello World 1")
}
t().then(() => {
console.log("Hello World 2")
})
console.log("Hello World 3")
如果执行此代码块,则日志输出如下
Hello World 1
Hello World 3
Hello World 2
我觉得这很奇怪,因为空循环花费的时间太长,因此输出应该是
Hello World 3
Hello World 1
Hello World 2
既然Hello World 3已经准备好执行,为什么Hello World 3没有先执行?
3条答案
按热度按时间yyhrrdl81#
您误解了JavaScript中“异步”行为的概念。
JavaScript是一种单线程语言,这意味着在主线程上一次只能执行一个东西。那么,“异步”意味着什么呢?
像HTTP请求这样的操作是异步的,但是JavaScript不能处理它们,我们编写的代码只是启动异步操作;实际的异步操作在客户端JavaScript的情况下由浏览器处理,或者在NodeJS运行时的情况下由后台线程或操作系统本身处理。
简而言之,异步操作在后台(JavaScript区域之外)进行,同时,其他操作可以在主线程上(JavaScript区域内)执行。
当异步操作完成时,JavaScript代码会得到通知,从而执行我们在启动异步操作时提供的回调函数。
在您的例子中,问题在于有一个长时间运行的循环在主线程上执行,因此,在循环执行期间,其他任何东西都不能执行。
以下步骤总结了代码的执行方式:
1.调用函数
t
并执行其中的代码。这一切都发生在代码的同步执行过程中。结果,长时间运行的循环阻塞了主线程1.循环结束后,在控制台上记录
'Hello World 1'
1.函数
t
结束;其返回的promise解析为undefined
的值,代码同步执行结束后异步调用t().then(...)
的回调函数1.在控制台上记录
"Hello World 3"
1.此时代码的同步执行已经结束,现在可以处理排队的任务了,本例中我们只有一个排队的任务,即
t().then(...)
回调函数的执行。回调函数异步调用,将
"Hello World 2"
记录到控制台。以下关于异步JavaScript主题的指南是了解此主题的好地方:MDN - Asynchronous JavaScript
7gcisfzg2#
仅仅在函数前面写async不会使它成为async。async只会使函数返回promise,但promise主体会立即执行。例如:
这里hello 1将再次首先执行。只有异步的函数将稍后运行。例如fs module。它将异步运行不是因为它被 Package 在promise中,而是因为它是以异步方式实现的。它使用libuv,而libuv又使用后台线程池来异步执行它。有几种方法可以使您自己的代码异步运行:
1.使用工作线程。你可以在你的代码运行的地方启动新的线程,这样你的主线程就不会被阻塞。
1.不太推荐,但有趣的方法,我尝试自己当我有同样的问题,你在过去-使用c++ API来建立自己的异步函数与nodegyp。它将使用线程池相同的方式fs或加密模块使用它。你可以阅读更多关于C++附加组件https://nodejs.org/api/addons.html。这是我的repo,我在那里测试构建它https://github.com/Edddo123/Native-Node-addons。让我知道,如果我能帮助你在其他方面
kyxcudwk3#
首先,你的代码不是异步的。
1.第一部分
t()
将被执行,它里面没有异步函数!所以for执行和hello world 1
打印。1.然后promise在异步模式下等待空闲!
hello world 3
打印。1.现在是检查是否履行承诺的空闲时间,请运行
hello world 2
。您可以将代码更改为: