JS同步与异步

JS同步与异步以及promise为什么比settimeout先执行

同步与异步

1
2
3
4
5
6
7
8
9
10
11
12
13
<script type="text/javascript">
console.log( "1" );
setTimeout(function() {
console.log( "2" )
}, 0 );
setTimeout(function() {
console.log( "3" )
}, 0 );
setTimeout(function() {
console.log( "4" )
}, 0 );
console.log( "5" );
</script>

执行结果为15234
结论:js先执行同步任务后才执行异步任务。
因为js是单线程的,所有任务都必须排队执行,所以如果前一个任务耗时很长,后一个任务就不得不等待。所以就有了任务队列的概念,将异步任务放入任务队列,只有在主线程完成了所有的同步任务后才进入任务队列的任务。

JS异步运行机制

  1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  2. 主线程之外,还存在一个”任务队列”(task queue)。只要异步任务有了运行结果,就在”任务队列”之中放置一个事件。
  3. 一旦”执行栈”中的所有同步任务执行完毕,系统就会读取”任务队列”,看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
  4. 主线程不断重复上面的第三步。

setTimeout与promise

1
2
3
4
5
6
7
8
setTimeout(function () {
console.log(1)
}, 0);
new Promise(function executor(resolve) {
resolve();
}).then(function () {
console.log(2);
});

虽然setTimeout先加入任务队列但结果仍然是21
总结来说,promise函数进入的是PromiseJobs的任务队列,而setTimeout进入的是ScriptJobs的任务队列。
当同步任务执行完,会先进入promise的任务队列,结束以后才进入setTimeout的任务队列。至于为何promise队列的优先级高,估计是为了用户体验吧:)
自己的理解,请勿转载