MandyJin / MandyJin.github.io

靳莹莹的博客
https://mandyjin.github.io/
1 stars 0 forks source link

js中promise,setTimeout 中顺序 #6

Open MandyJin opened 6 years ago

MandyJin commented 6 years ago

node和chrome js执行引擎都是以V8为核心的。因此,在异步事件处理上十分相似。 在node中,异步分为两种,一种是IO的异步,一种是非IO的异步。 异步IO有磁盘IO和网络IO,非IO异步有process.nextTick, promise, setTimeout, setImmediate.。 非异步IO中,process.nextTick, promise等属于microTask, setTimeout, setImmediate 是macroTask。 异步IO的调用需要底层libuv层支持,较为复杂,属于macroTask。

比如,在js中发起一个网络请求时,js代码调用node核心模块,核心模块再调用C++内建模块。内建模块通过libuv进行系统调用。系统调用的过程中,创建相应的请求对象,从js层传入的参数和当前方法都被封装在请求对象中,回调函数被设置在请求对象的oncomplete_sym上,对象包装完毕后,调用QueueUserWorkItem将请求对象推入线程池中等待执行。

js层继续执行后续执行栈中的代码。

在内核层,当线程池中有空闲线程时,调用相应底层函数,发起网络请求。

在v8是单线程的,但是浏览器和操作系统是多线程的(!important)。(意味深长~~)

此时,JavaScript调用立即返回。根据当前的执行栈,继续执行原执行栈的函数。检查microTask中是否任务可以执行,若有,则按照优先级、调用先后顺序依次执行,直到将microTask执行结束。

网络请求对象送入IO线程池等待执行,内核利用端口发起真正的网络请求,并侦听网络端口,一旦接收到网络请求,表示内核层面的网络请求执行完毕。

执行完毕后,会将结果储存在请求对象的result属性上。window下调用PostQueuedCompletionStatus通知IOCP,告知当前对象操作已经完成,并将线程归还线程池。

内核发送IO观察者形成事件,每次Tick时,调用GetQueuedCompletionStatus获取执行状态,得到执行完的IO操作,将请求对象加入IO观察者队列中,将其当作事件处理。

网络IO属于macroTask,这个macroTask放入event loop中。event loop中的异步IO都有相应的观察者,每次tick,检查优先级较高的观察者。

process.nextTick 属于idle观察者,setImmediate是check观察者。idle观察者优于IO观察者,IO观察者优于check观察者。

如有IO观察者回调函数,取出请求对象的result作为参数,在js层回调执行,结束调用。

然后检查microTask,执行所有microTask函数。同时,microTask在event loop中也有优先级。

MandyJin commented 6 years ago

nodejs 事件驱动和事件循环

nodejs是单线程(single thread)运行的,通过一个事件循环(event-loop)来循环取出消息队列(event-queue)中的消息进行处理,处理过程基本上就是去调用该消息对应的回调函数。消息队列就是当一个事件状态发生变化时,就将一个消息压入队列中。

nodejs的事件驱动模型一般要注意下面几个点:

包括:script(整体代码),setTimeout,setInterval,setImmediate,I/O,UI rendering.

jobs

包括:process.nextTick,Promise,Object.observe(已废弃),MutationObserver(监视DOM变动的接口).

事件循环的顺序,决定了javascript代码的执行顺序。它从script(整体代码)开始第一次循环。之后全局上下文进入函数调用栈(消息队列?)。直到调用栈清空(只剩全局),然后执行所有的 jobs。当所有可执行的 jobs 执行完毕之后,循环再次从 task 开始,找到其中一个任务队列执行完毕,然后再执行所有的 jobs,这样一直循环下去。

MandyJin commented 6 years ago

https://github.com/Myoursky/MyBlog/issues/20

MandyJin commented 6 years ago

https://github.com/libin1991/libin_Blog/issues/131

MandyJin commented 6 years ago

https://github.com/Guocover/blog/issues/7

MandyJin commented 6 years ago

https://github.com/djq1996/djq-blog/issues/4

MandyJin commented 6 years ago

http://www.qdfuns.com/notes/17659/7cb0a395fea126caceeb64909b594b0f.html

geometrybase commented 6 years ago

https://github.com/geometrybase/test.git