1. javascript单线程
首先需要明确一点,无论是浏览器中还是nodejs中的javascript,从应用层面上来讲,都是单线程的。
注:Html5中引入了
Web Worker来实现多线程,但是无法操作DOM,而且Web Worker完全受主线程控制。
2. Event Loop
浏览器中的Event-loop模型与NodeJs中的模型是不一样的,我们本文主要以浏览器中的javascript为主,NodeJs只做简单说明。
2.1 浏览器中的Event-loop
个人理解Event Loop应该指的是一系列的概念,其中包括执行栈-主线程(Stack),任务队列-(callback queue),还有Event-Loop。
上面的这些名词来自于这篇文章:vimeo.com/96425312
1) 简单工作工程 (如下图所示)
- 浏览器会扫代码中所有的
IO操作。 - 异步操作会交由
IO去执行,执行完毕后将IO操作对应的回调函数放到callback queue中。 - 当主线程中所有的同步任务执行结束后,会检查
callback queue中是否有执行结束的回调,如果有就执行。
2) 可以添加callback到callback-queue
可以通过setTimeout()方法,将function手动设置到callback-queue中,这样就可以控制某些function的执行顺序。
display(`This is the 1st time to call display()...`);
setTimeout(function() {
display(`This is the 2nd time to call display()...`);
}, 0);
display(`This is the 3rd time to call display()...`);
/**
* 输出结果:
* This is the 1st time to call display()...
* This is the 3rd time to call display()...
* This is the 2nd time to call display()...
*
* 因为1st和3rd的调用这两句代码是同步任务放到了主线程执行栈中执行。
* 2nd这句我们通过调用setTimeout方法放到了callback-queue中,只有主线程中的所有任务执行完成后,才会调用callback-queue中的任务。
*/
2.2 NodeJs中的Event-loop
V8引擎解析javascript脚本。- 解析后的代码,调用
Node API。 libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop,以异步的方式将任务的执行结果返回给V8引擎。V8引擎再将结果返回给用户。
NodeJs的内容引自阮一峰老师的blog: www.ruanyifeng.com/blog/2014/1…
NodeJs中还引入了process.nextTick()和setImmediate()。
nextTick(): 在当前队列尾部添加回调,也就是说nextTick()设置的回调会在下次队列执行前执行。setImmediate(): 在下一队列头部添加回调,也就是说setImmediate()设置的回调会在下次队列执行时执行。
3. Promise对象
Promise对象是javascript中引入的异步对象,Pomise内部有两个对象:resolve/reject。resolve用来定义异步执行结果成功后的回调函数,reject用来定义异步执行结果失败后的回调。而且,在reactjs与vue.js中,非常方便的使用Promise对象支持async - await模式。由于本例中使用babel7的script模式,所以支持async - await的demo比较复杂,就不演示了。
// 如何在javascript中使用promise
function simpleExample(text) {
return new Promise((resolve, reject) => {
if (text == undefined || text === '')
reject('error');
console.log(text);
resolve('done');
});
}
var result1 = simpleExample();
var result2 = simpleExample('hello');
result1.then(value => console.log(value)).catch(err => console.log(err)); // error
result2.then(value => console.log(value)).catch(err => console.log(err)); //hello
Promise对象中的执行顺序是如何的呢?
Promise中的逻辑将会在Promise对象构造时立即执行Promise中resolve/reject的回调,将会在执行结束后,被放到下一个消息队列的头部
setTimeout(function(){
console.log(`promise eventloop: ${1}`);
});
var promise = new Promise(function(resolve){
console.log(`promise eventloop: ${2}`);
resolve();
});
promise.then(function(){
console.log(`promise eventloop: ${3}`);
});
console.log(`promise eventloop: ${4}`);
/**
* promise eventloop: 2 当promise构造时,promise中的逻辑将立即执行
* promise eventloop: 4 第二步,执行主线程中的任务
* promise eventloop: 3 promise.resolve中的回调函数,将会被放到callback-queue的顶部执行
* promise eventloop: 1 setTimeout中的逻辑会放到callback-queue中
*/