【javascript】异步-事件轮询-任务队列-工作队列(job queque)
异步
异步编程的核心: 现在 与 稍后 的部分之间的关系。
例子: 去吃饭排队,先拿一个号,排到了手机会有消息收到。在这个时候,可以取买点喝的。
现在:排队拿号 -> 买水 。
稍后:短信通知排到了,开吃!
event loop 事件轮询
我们将事件轮询理解成一个永动机,它一直会去找某一个队列【就可以理解成一个数组】里面的是否有执行的任务,如果有,那么会去执行。
模拟代码:
var eventLoop = [];
var event;
// 永远执行
while (true) {
// 检查队列是否有数据
// 执行一个tick
if (eventLoop.length > 0) {
event = eventLoop.shift();
try {
event();
}
catch(err) {
reportError(err); // report Error stack info
}
}
}
js引擎 遇到异步代码块,会将它放到【不一定是马上】任务队列里面,当主线程执行完所有代码的时候,会从这个任务队列里面取任务,如果有就执行。
setTimeout 不会将回调放在事件轮询队列上,定时器超时的时候,环境才会把你的回调放进事件轮询,这样在未来的某个tick中将会被取出执行。
虽说js是单线程,但是在事件轮询 和 并发模型机制上,并非是单线程。 除了主线程callstack , 还有一个专门处理回调函数或者事件的线程(在浏览器里面就是webAPI,node里面就是线程 )。外面有一个task queue,这里就是回调等待的地方。
比如遇到了A , A 有一个回调,A函数执行了,A的回调放到了 另外的线程,另外的线程在满足一定条件(可能是setTimeout 或者response响应)之后就会将这个回调放到 task queue 里面, callstack [必须]clear之后会马上去task queue 里面一个一个执行这个队列的代码,执行完一个,task queue的这个就回收。
nice video: https://www.youtube.com/watch?v=8aGhZQkoFbQ
[大白话]: 主线程的代码执行完毕之后,然后会去task queue(任务队列)去执行队列中的任务。
所以
console.log("one")
setTimeout(()=>{
console.log("two")
}, 0)
console.log("three")
结果会是:
"one"
"three"
"two"
而不是one two three
。
但是ES6 引入了promise generator async 等异步概念,他们是不是也是被放到了task queque呢。。答案是否定的。
在任意特定的时刻
,一次只有一个队列中的一个事件可以被处理,当事件执行的时候,它可以间接的或者直接的引发(导致)一个或者更多的后续事件。
es6引入了新的概念:job queque(工作队列)
, Promise的异步行为是基于job的
to be continued