ES5实现Promise(1)|ES5实现Promise(1) - 事件循环机制

? 因为公司业务面向国企以及传统企业,所以代码需要能够在ie9以上运行,所以在项目中无法用一些新技术。比如ES6的Promise,这个Promise真的是太好使了,就跟便秘时使了开塞露一般。由于Promise太好使了,所以这两天想着能不能用ES5实现Promise。在网上搜到了很多关于ES5实现Promise的文章,大部分都是说需要先明白JavaScript的时间循环机制。正好这块我以前也不是非常明白,这次也正好仔细学习一下。
? JavaScript是一种单线程非阻塞的语言。单线程就是指代码在执行的时候,只有一个线程来处理所有任务。非阻塞则指的是当代码在执行一项无法立即返回结果的任务时,就会先将这个任务挂起(pending),待到其他这个任务返回结果后再按照一定的规则进行操作。其实非阻塞就是用异步操作来完成的。用代码可以表示成:

console.log(1); setTimeout(function(){ console.log(2); },1000); console.log(3);

? 这段代码就是一个用异步操作来实现非阻塞的例子。代码最后执行结果是1 3 2。这段代码翻译下来就是:首先在控制台答应1,打印完了之后就会执行setTimeout方法,这个方法是计时1000毫秒,这个1000毫秒就表示无法立即返回执行的结果,所以此时会将setTimeout方法挂起,挂起后setTimeout就会自顾自计时去了。主线程将将setTimeout挂起后就继续执行后边的语句去了,所以会在控制台打印3。现在主线程上的任务都已经处理完了,待setTimeout计完时,就是执行其回调函数,也就是在控制台打印2。
? 说回JavaScript的事件循环。JavaScript执行方法的时候,会生成一个执行环境,这个环境满足了执行这个方法的条件。当遇到一系列的方法后,就会将遇到的方法,依次添加到执行栈。当JavaScript第一次执行时,主线程会将所有的同步代码按照执行顺序添加到执行栈中。当遇到的这个代码是个方法时,就会将这个方法的执行环境添加到执行栈中,然后进入这个执行环境,执行方法中的所有代码。执行完了之后就会退出这个执行环境并销毁这个环境,然后就继续执行执行栈中的下一个语句。当主线程执行代码时遇到一个异步代码时,就会将其挂起,期间继续执行执行栈中的语句。当这个挂起的方法执行结束之后,结束后的方法并不会立即添加到当前的执行栈中,而是将这个方法添加到了事件列表中,当执行栈中的代码全部执行完了之后,主线程就会去事件列表里执行里边已经有的方法。
console.log(1); setTimeout(function(){ console.log(2000); },2000); setTimeout(function(){ console.log(1000); },1000); console.log(3);

上边这段代码执行时,会先将console.log(1)添加到执行栈,然后就遇到了第一个setTimeout,这是一个异步操作,所以将其挂起执行,挂起后主线程就继续往下执行,又是一个异步操作,所以继续挂起执行,然后主线程继续执行,这会不是异步操作,所以将这个console.log(3)添加到执行栈。暂时先不管执行栈里的代码有没有执行,先看看之前挂起的两个方法,计时时间为1000毫秒的当然先执行完,这个时候就将其回调函数添加进事件列表,等待执行。然后计时2000毫秒的也计完时了,他的回调函数也就进入了事件列表。上边也说了,主线程会在将执行栈里的代码全部执行完了之后再去执行事件列表里的代码。所以会先在控制台打印1 3,这时执行栈里的代码就全部执行完了,然后主线程就去执行事件列表里的代码。这时就会先将事件列表里的第一个代码放到执行栈里,再将第二个代码放进执行栈。所以就先后打印出1000和2000。如果回调里套异步,异步的回调里套异步。这时候主线程就会在执行栈和时间列表一直跑,从而形成了一个循环,这就是事件循环机制了。
【ES5实现Promise(1)|ES5实现Promise(1) - 事件循环机制】? 事件循环机制就是这样。以上文字供我自己之后参考,掺杂大量个人理解和口语化表达,难免和官方有所偏差,一切以官方或大佬为准。

    推荐阅读