JS同异步编程

js有三个大问题:作用域,原型链,同异步

同异步想要知道同异步问题就要找到js的运行机制:

js是单线程:同一时间只能执行一件事情

浏览器是多线程:同一时间内能执行多件事情

为什么js是单线程:假如有2个函数同时执行,一个是添加元素,一个是删除元素,浏览器就不知道该如何执行,所以js设计成了单线程

例如在浏览器中打开一个HTML页面的时候,就占用了一个进程,浏览器分配一个线程去计算DOM树,分配其他线程去加载对应的资源文件,再分配一个线程去自上而下执行js

可以查看浏览器控制台的Network,有很多线程在进行

同步:在一个线程上(主栈 / 主任务队列)同一个时间只能做一件事情,当前事情完成才能进行下一个事情(先把一个任务进栈执行,执行完成,再进行下一个进栈,上一个任务出栈)

异步:在主栈中执行一个任务,发现这个任务是异步的操作,会把异步操作移出主栈,放到等待任务队列中,这个时候浏览器会再分配其他线程监听异步任务是否到达指定的执行时间,等待主栈执行完,监听者会把到达时间的异步任务,重新放到主栈中执行

在js中,分为执行队列和等待队列,当遇到异步任务,会把该任务对应的回调函数放到等待队列中,当执行队列中执行完毕,再去等待列队查看满足条件的任务,把其对应的回调放到主任务队列中执行,主任务队列也叫执行栈

所谓js中的异步编程仅仅是根据某些机制来管控任务的执行顺序,不存在同时执行两个任务一说

在js中异步执行的有:setTimeout / set  、ajax 、事件绑定,回调函数,Promise(async / await)、node的process.nextTick、node的fs的I/O操作

setTimeOut(()=>{
  console.log(1);//再输出1
},10)

for(let i=0; i<1000; i++){//同步
}
console.log(100); //先输出100 
let xhr = new XMLHttpRequest();//第一步进栈new一个实例后再出栈
   xhr.open('GET','XXX.JSON',false);//第二步进栈 执行open后再出栈,设置为同步 此时 readyState=1
   xhr.onreadystatechange=function(){//此时进栈发现监听事件是异步,放等待任务中,此时 readyState=1;第四步当执行完send,readyState=4的时候 执行异步
       console.log(xhr.readyState);//readyState=4
   }
    xhr.send();//第三步执行 同步任务send ,此时readyState=4的时候主栈空闲

ajax开始是send开始,结束是状态为4结束

 let xhr = new XMLHttpRequest();//第一步进栈new一个实例后再出栈
   xhr.open('GET','XXX.JSON',false);//第二步进栈 执行open后再出栈,设置为同步 此时 readyState=1
    xhr.send();//第三步执行 同步任务send ,此时readyState=4,结束
   xhr.onreadystatechange=function(){//状态改变的时候才会触发监听,放等待队列的时候状态已经是4了,不会再改变了,所以不会执行这个方法了
       console.log(xhr.readyState);//一次都不输出
   }
   let xhr = new XMLHttpRequest();//第一步进栈new一个实例后再出栈
   xhr.open('GET','XXX.JSON',true);//第二步进栈 执行open后再出栈,设置为异步 此时 readyState=1
    xhr.send();//第三步执行 同步任务send ,会有一个线程是去请求数据,主栈空闲下来,此时readyState=1,
    //发现异步,放等待队列中,此时readyState=1
   xhr.onreadystatechange=function(){//主栈空闲了,readyState变成2,函数执行一次,
                                      //状态为3的时候,又执行一次,
                                       //状态为4的时候,把函数又执行一次
       console.log(xhr.readyState); //2,3,4
   }

js事件:主线程不断的重复获得消息,执行消息,再取消息,再执行...事件循环

宏任务和微任务

主线程每次只能执行一个任务,当主线程执行完毕,会首先去微任务队列中去获取第一个执行任务,当把微任务中的任务队列中的任务执行完成,才去宏任务队列去寻找该执行的任务

宏任务:定时器,ajax,setImmendiate

微任务:promise的then,async await , process.nextTick

如果遇到了多个微任务,谁先放入谁先执行,微任务执行完毕,再去执行宏任务

原文地址:https://www.cnblogs.com/xinxinxiangrong7/p/11440351.html