javaScript Event loop

1.JavaScript是一门单线程语言,单线程意味着他只有一个栈,一次只能去作一件事情,因此要知道他是如何去处理异步问题还得搞清楚JavaScript的代码执行运行机制。javascript

  首先咱们先写一段简单同步线程的代码java

 function one(n){console.trace(n);}
 function tow(n){one(n)}
 function three(n){tow(n)}
 three(3)promise

 

如图所示callStack中是正在执行的代码,咱们使用console.trace()打印此时调用站(callStack)的状况,下图的执行结果让咱们了解到函数的调用顺序是一种后进先出的规律。浏览器

 

 

 

2.那么它是如何解决异步问题的呢?(task queues异步

咱们先提一个概念    “任务队列task queues)“函数

由如下代码咱们能够知道settimeout会延迟一秒执行,他在执行前会被放入一个任务队列当中(task queues),并不会直接去执行,等待 callStack 中的事件所有完成的时候 event loop才会去将taskQueues中的事件调到callStack中执行oop

console.log('start');

setTimeout(()=>{
    console.log('waiting')
}
, 1000)

console.log('end');

  输出结果                                      因为setTimeout没有返回值因此他会先抛出undefined再等待一秒钟后打印fetch

 

 

 3.异步队列也有执行优先级!(Microtasksthis

1.macrotaskspa

 

 

 在等待回调的任务当中他们也分两种任务,macrotask queue就是咱们常说的task queue。Macrotask包括了setTimeout, Dom 操做 click/onLoad/mouse事件绑定,fetch then response这类操做。实际上这些都是浏览器提供的API,因此在执行时是有它们单独的线程去进行操做。举个例子,setTimeout()设置了2s的延迟,是浏览器设置了timer来计时,是另外的线程在等待2秒,js主线程不受影响,2s后回调函数再进入task queue。

(function() {

  console.log('this is the start');

  setTimeout(function cb() {
    console.log('this is a msg from call back');
  });

  console.log('this is just a message');

  setTimeout(function cb1() {
    console.log('this is a msg from call back1');
  }, 0);

  console.log('this is the end');

})();

 

 

 event loop会将先有返回的任务放入callstack中 若是cb若和cb1无时间差则按照先进先出的执行顺序

2.Microtask

ES6提供了Promise来进行异步操做。microtask。同上也有一个队列(job queue)来处理microtask。job queue拥有更高的优先级。每一个task结束后,都会检查microtask队列是否有任务在等待执行,根据先进先出,依次执行。

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

 

 

 因为macrotask的队列(task queues)比  Microtask 的队列(job queues)优先级低因此setTImeout的打印内容最后执行

3.总结 event loop

eventloop 当callstack为空时去检查队列是否有须要执行的任务,执行顺序跟根据先进先出的规则执行,执行的Microtask(Promise) 队列比macrotask(setTimeout/DOM events/fetch)队列优先级高,Microtask 中的任务会先执行,当Microtask中的队列任务所有执行完毕以后才会去执行macrotask队列中的任务,固然最大的前提仍是callstack得先执行完成

while (queue.waitForMessage()) {
  queue.processNextMessage();
}
相关文章
相关标签/搜索