当JavaScript是单线程语言时,如何在JavaScript中使用异步无阻塞代码?
我是JavaScript新手,我习惯于通过创建工作线程在Java中创建异步无阻塞代码 我不明白异步无阻塞代码在JavaScript中是如何工作的,因为JavaScript是一种单线程语言 例如,JavaScript中的承诺和回调 两者都是无阻塞的,并且允许主线程继续逐行执行程序的其余部分,并且仅当承诺在稍后时间(例如:数据准备就绪)得到满足时,才会执行promise.resolve()或回调 现在,我很难理解,如果主线程已经移动,并且正在忙于做不同的事情,那么哪个线程确切地跟踪承诺何时实现/准备就绪,或者回调何时准备好执行 作为一名Java程序员,我的逻辑告诉我,必须有一个后台工作线程,负责在回调/承诺准备好执行时通知主线程,这与JavaScript是单线程的事实相矛盾,所以我一定错了 我想对这个概念有一个很好的解释。当JavaScript是单线程语言时,如何在JavaScript中使用异步无阻塞代码?,javascript,asynchronous,async-await,es6-promise,Javascript,Asynchronous,Async Await,Es6 Promise,我是JavaScript新手,我习惯于通过创建工作线程在Java中创建异步无阻塞代码 我不明白异步无阻塞代码在JavaScript中是如何工作的,因为JavaScript是一种单线程语言 例如,JavaScript中的承诺和回调 两者都是无阻塞的,并且允许主线程继续逐行执行程序的其余部分,并且仅当承诺在稍后时间(例如:数据准备就绪)得到满足时,才会执行promise.resolve()或回调 现在,我很难理解,如果主线程已经移动,并且正在忙于做不同的事情,那么哪个线程确切地跟踪承诺何时实现/准备
提前谢谢 使用计算机实现并发行为有两种方法:
您可以将JavaScript引擎看作是一个
任务执行器
,它在线程池
中启动线程。但是,您只控制任务执行器承诺/回调被阻止
。您可以运行以下示例:
function func1() {
return new Promise(resolve => {
setTimeout(() => {
console.log('func1');
while (true) {}
resolve();
}, 0);
});
}
function func2() {
func1();
func1();
console.log('func2');
}
func2();
您将看到func1
只打印一次,因为第一个执行func1()的承诺会阻止第二个被调用
您可以考虑将每个代码块放置在事件循环的队列中。
对于异步调用,代码的异步部分已排队,等待事件循环运行。当然,事件循环本身是JavaScript应用程序中的单个线程 例如,如果将while循环移动到func2()
的末尾,将永远看不到打印出func1
,因为函数func2()正在阻塞队列,因此承诺将永远无法解析
充当调度程序的“线程”应该是应用程序之外的另一个线程,但由于它不是应用程序的一部分(由JavaScript开发人员/用户编写),我不认为JavaScript不是“单线程语言”。它基于事件。运行时等待事件发生,并在事件发生时调用事件处理程序。构建在JavaScript之上的运行时(如WebAPI和node.js)是多线程的,并提供异步特性。像
setTimeout
这样的东西不是JavaScript的一部分,而是运行时。您应该研究事件循环及其工作原理。请注意,您的两个示例是错误的,承诺和回调是阻塞的。立即解析的承诺只会被推到当前执行任务的末尾,但如果继续在循环中直接解析承诺,则会阻塞整个线程。调用回调的任务可以是异步的,而不是回调本身;但是这个任务也很可能不是用javascript编写的;-)非常感谢大家的宝贵意见,非常感谢!非常感谢您的澄清,非常好的示例代码!非常感谢!非常感谢。很好的解释!