JS 同步异步,宏任务和微任务

本人看到各个文章的知识概念,结合自己的理解记录一下把,可能有些概念理解的不是很对。待以后有时间不断的深入理解再进行更新把
知识补充

1、JavaScript是单线程,而浏览器是多线程。
2、浏览器包括的线程有:事件触发线程、定时器触发线程、异步http请求线程、GUI渲染线程
3、异步任务区分了宏任务和微任务(当然所有的JS代码也可以看作宏任务)
4、栈符合数据结构中的先进后出,队列符合先进先出
5、创建Promise或async的过程是一个同步操作,reslove.then或await阻塞之后的内容才是异步

同步任务:

因为JavaScript的单线程,因此同个时间只能处理同个任务,所有任务都需要排队,前一个任务执行完,才能继续执行下一个任务。这便是同步。

同步类似:吃饭的操作,饭是要一口一口吃的。因为嘴只有一个。哈哈哈。

异步任务:

当遇到异步任务的时候,也就是假如遇到Ajax,promise等异步操作时候。要请求的接口多的时候(如图片、音乐、视频、文件等),当然不可能一个一个等。如果都一个一个等待的话,页面就会卡顿主会影响用户体验。所以JS引擎会把异步任务先挂起通过浏览器中的其他线程将异步任务放到任务队列中去处理,等有结果后才会通知主线程可以去调用了,这样主线程上可以先执行其它的同步任务。(因为JS是单线程,这时浏览器的线程如异步http请求线程、定时触发器线程、事件触发线程会进行辅助JS进行异步处理)

异步类似:我桌子上放着好多菜,但有些菜很烫或者菜还没有上齐,但我饿了,我就可以先吃一个当下可以能吃的菜,等其他菜凉了或上了别的菜我再分别去尝着吃

宏任务&微任务

ES6 规范中,macrotask(宏任务) 称为 task,microtask(微任务) 称为 jobs
宏任务是由宿主(浏览器或Node.js)发起的,而微任务由JavaScript引擎自身发起。

执行顺序:先微任务,后宏任务
每次宏任务会触发新一轮的Tick

宏任务包括:
  1. script (可以理解为最外层同步代码)
  2. setTimeout/setInterval
  3. UI rendering/UI事件
  4. postMessage,MessageChannel
  5. setImmediate,I/O(Node.js)
微任务包括:
  1. Promise
  2. MutaionObserver
  3. Object.observe(已废弃;Proxy 对象替代)
  4. process.nextTick(Node.js环境中其优先级高于Promise)
事件循环(Event Loop)

JS 同步异步,宏任务和微任务_第1张图片

当执行栈为空时(JS引擎线程空闲),事件触发线程会从消息队列中取出一个任务(异步的回调函数)放入执行栈中执行。执行完毕后执行栈再次为空,事件触发线程会重复上一步操作,继续从消息队列中取出一个任务。此机制被称为事件循环(event loop)机制。每一次循环称为tick

简化:

  1. 所有同步任务都在主线程上执行,行成一个执行栈
  2. 主线程之外,还存在一个任务队列,只要异步任务有了结果,便会将其回调返到消息队列
  3. 一旦执行栈中的所有同步任务执行完毕,系统就会读取消息队列的回调函数,于是结束等待状态,进入执行栈,开始执行
  4. 主线程不断的重复上面的第三步
示例代码:
console.log("script start");

async function async1() {
  await async2();
  console.log("async1 end");
}
async function async2() {
  console.log("async2 end");
}
async1();

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

new Promise((resolve) => {
  console.log("Promise");
  resolve();
})
  .then(function () {
    console.log("promise1");
  })
  .then(function () {
    console.log("promise2");
  });

console.log("script end");

结果:
	script start
	async2 end
	Promise
	script end
	async1 end
	promise1
	promise2
	setTimeout


结论:
    先走同步,会将所有代码放进执行栈中,先执行同步,而异步不执行(当消息队列返回回调才会执行)
    遇到异步,便会将所有异步放入任务队列中,再任务队列中又分为宏任务队列和微任务队列
    再异步的顺序中,会将微任务代码依次从任务队列放入消息队列,再消息队列中返回一个回调函数,最后事件线程会将其放入执行栈中(不断重复的过程也就是Event Loop 调用过程)

你可能感兴趣的:(文章,javascript)