那就先问个问题吧😁。javascript
单线程意思就是说同一个时间只能作一件事。那这样的话效率不是很低?也没有啦,其实javascript的单线程特色是跟他的用途有关的。做为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操做DOM。假如不是单线程的话,在一个线程当咱们在给某个DOM节点增长内容的时候,另外一个线程正在删除这个DOM节点的内容,那还得了,那不是乱套了吗。因此javascript只能是单线程。html
若是在一个函数返回的时候,调用者就可以获得预期结果(即拿到了预期的返回值或者看到了预期的效果),那么这个函数就是同步的。
java
用代码解释一下:node
console.log('Hello');
复制代码
若是在函数返回时,就看到了预期的效果:在控制台打印了Helloajax
若是在函数返回的时候,调用者还不可以获得预期结果,而是须要在未来经过必定的手段获得,那么这个函数就是异步的。
promise
代码解释:浏览器
fs.readFile('test.txt', 'utf8', function(err, data) {
console.log(data);
});
复制代码
在上面的代码中,咱们但愿经过fs.readFile函数读取文件foo.txt中的内容,并打印出来。可是在fs.readFile函数返回时,咱们指望的结果并不会发生,而是要等到文件所有读取完成以后。若是文件很大的话可能要很长时间。bash
同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。
异步
异步方法调用更像一个消息传递,一旦开始,方法调用就会当即返回,调用者就能够继续后续的操做。而,异步方法一般会在另一个线程中,“真实”地执行着。整个过程,不会阻碍调用者的工做。函数
上面说过了javascript里面的任务有两种,同步任务和异步任务。
同步任务是指:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。
异步任务指的是,不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务能够执行了,该任务才会进入主线程执行。
先看个小栗子吧:
console.log("a");
setTimeout(function () {
console.log("b");
},0);
console.log("c");
//a
//c
//b
复制代码
js中代码从上往下执行,执行第一行代码的时候控制台输出a,执行到第二行代码的时候遇到了setTimeout函数,由于setTimeout函数是个异步函数,因此,浏览器会记住这个事件,添加到时间表中,以后把这个事件的回调函数入栈到任务队列中。而此时主线程程序继续往下运行,到了第五行:console.log("c"),执行这条,控制台输出c。这时候主线程空了,他会到任务队列里面去查找是否有能够执行的任务,有的话直接拿出来执行,没有的话会一直去询问,等到有能够执行的。
事件循环其实就是入栈出栈的循环。上面例子中说到了setTimeout,那setInterval呢,Promise呢等等等等,有不少异步的函数。可是这些异步任务有分宏任务(macro-task)和微任务(micro-task):
macro-task包括:script setTimeout, setInterval, setImmediate, I/O, UI rendering。
micro-task包括:process.nextTick, Promises, Object.observe, MutationObserver。
每一次Event Loop触发时:
在浏览器浏览器和node中的执行不同。
任务队列里面是“先入先出”的。
console.log('global')
for (var i = 1;i <= 5;i ++) {
setTimeout(function() {
console.log(i)
},i*1000)
console.log(i)
}
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('then1')
})
setTimeout(function () {
console.log('timeout2')
new Promise(function (resolve) {
console.log('timeout2_promise')
resolve()
}).then(function () {
console.log('timeout2_then')
})
}, 1000)
复制代码
控制台输出:
这里主要是讲了在浏览器端js事件循环。这篇文章能够帮助更好的理解node和浏览器环境下不一样的事件循环:浏览器和Node不一样的事件循环(Event Loop)