Javascript 事件循环和 promise 对象

科技 2017-08-21 0 条评论 访问: 169 次

javascript-event-loop-1-638.jpg

Javascript是单线程,事件驱动,异步处理IO的编程语言。处理异步操作,在promise对象出现之前有async,eventproxy,q等第三方库(它们很棒)。说道单线程,难道 JS 在进行IO操作或者ajax获取数据的时候就傻傻的等待(同步),阻塞线程不做任何事吗?当然不是,这都要归功于事件循环和异步机制。从被玩儿坏的setTimeout说起吧~

异步编程

console.log('start')
setTimeout(function (){
    console.log('tickta...tickta')
}, 3000)
console.log('end')
//start
//end
// 3 secs later...
//tickta...tickta

此时一直使用C语言的同学可能感到匪夷所思了。「笑」

事件循环机制

JS 有一个主线程,用来处理事件。当js开始运行时,把所有非回调函数依次放到JS主栈,此例中setTimeout也是非回调函数,它执行的效果是在工作线程中增加一个计时器。还有一些工作线程(来自Node环境或者浏览器环境,浏览器环境下应该叫Web API),来处理文件操作,数据库读写操作,ajax请求。每当工作线程完成一件工作就要通知主线程,通知方法就是把这些通知(回调函数)放到任务队列(task queue)里面。当JS主栈空了以后——可以理解是执行了一轮——就从任务队列里面依次取出回调函数放入主栈执行。如果回调函数里面还有回调函数就把它们放入任务队列等待下一轮运行。用一张图来说明
sample31.png

异步任务分两种,有宏任务(macro-task)和微任务(micro-task)。JS引擎按照不同类型把任务分配到这两个队列,首先从macro-queue中取出一个任务执行,然后取出micro-queue中所有任务依次执行,再取出macro-queue中一个任务执行,如此循环直到队列中的任务执行完毕。
两个类别的分类具体如下:
macro-task: script(整体代码),setTimeout,setInterval,setImmediate,I/O,UI rendering
micro-task: process.nextTick,Promise,Object.observe,MutationObserver
process.nextTick > promise.then > setTimeout > setImmediate
如果是浏览器环境,执行顺序也有依赖于实现。Chrome,Firefox,IE都不一样,node环境和Chrome一样

Promise 对象

Promise对象的初始化需要重写(说重写可能对熟悉Java的同学比较好理解,或者说赋给他一个)它的function(resolve, reject){}方法,该方法内部的代码会立刻执行,就好象它们直接写在函数外面一样。如果执行了resolve那么代表任务成功,将来会执行then里面的代码,如果执行了reject将来会执行catch里面的代码

b02af2fc6dabdc10f7f623b9baaa28f9.jpg

setTimeout(function() {
    console.log(1)
}, 0)
var p = new Promise(function(resolve, reject) {
    console.log(2)
    for(var i=0; i<10000; i++) {
        i === 9999 && resolve()
    }
    console.log(3)
}).then(function() {
    console.log(4)
}).then(function() {
    console.log(5)
}
console.log(6)

执行结果
2
3
6
4
5
1
fa86402457771a0d3a7e0d4cda4cea44.jpg

先执行macro-queue的一个任务,也就是 script ,然后依次执行micro-queue的所有任务,也就是 then 里面的,再执行macro-queue的一个任务,也就是 setTimeout
queues.png

参考资料:

知乎上关于 Promise 的考证
一个可视化代码执行过程,有点小 bug
Viemo 上关于事件循环的演讲,需要科学上网
浏览器环境下的事件循环


除非注明,嗯VIEW文章均为原创,转载请以链接形式标明本文地址
本文地址:https://www.umview.com/javascript-eventloop-promise

本文由 Mark 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论