js中同步队列、异步队列

单线程多线程

单线程模型:历史延续,JS是单线程模型,它在同一时间只能执行一个任务,其他的任务在后排队等待。
多线程模型:一次执行多个任务。

你的电脑开了很多的软件,打开任务管理器其实可以看到,这些软件都会开各自的进程,这些进程里有分为很多的线程,这些线程就相当于这个软件里的很多引擎,他们可以同时干着很多的事情。就像你开车一样,方向盘,发动机,空调等等,把汽车比做进程,那这些东西就是线程,他们可以同时干着自己的事情。

js中同步异步

同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的,同步的;同步任务都在主线程上执行,形成一个执行栈;
异步:同时执行多个任务,异步任务(大部分异步任务为回调函数)会被放在任务队列当中

js的执行是单线程的,那为什么我们平时看得的几十个接口请求可以同时返回来数据呢?那是因为js执行分为同步和异步,在浏览器分为两个队列,一个是同步队列,一个是异步队列。同步队列一般放那些同步代码的,比如console.log()、var a = 5;等等。异步队列有AJax请求定时器事件回调函数等等。这里顺便提一嘴,服务端一般都是异步的,你想象一下假设服务端是同步的,那么我10个接口过来,它得一个接口完全返回数据之后在执行下个接口,这不得卡死。那这同步队列异步队列执行的机制是什么样子的呢?

JS执行机制

  • 先执行执行栈中的同步任务

  • 异步任务(回调函数)放在任务队列中

  • 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行.

 js的运行环境

js的运行环境=>浏览器。那么这个环境有哪些引擎呢?

渲染引擎:负责页面的渲染
js引擎:负责js的预处理、解析和执行等
定时触发器引擎:负责处理定时事件,比如setTimeout,setInterval
事件触发引擎:负责处理dom事件
异步http请求引擎:处理http请求

这里要注意一下,渲染引擎和js引擎不能同时进行,渲染引擎在执行任务的时候,js引擎会被挂载,这是因为js引擎可以修改dom,如果一边渲染一边修改dom,浏览器也不知道怎么办好了。 

宏任务和微任务

异步任务队列里又分宏任务和微任务。宏任务队列可以有多个,但是微任务队列只有一个

宏任务:script(全局任务),setTimeout,setInterval
微任务:process.nextTick, Promise, Object.observer

看个例子

setTimeout(_ => console.log(4))

new Promise(resolve => {
    resolve()
    console.log(1)
}).then(_ => {
    console.log(3)
})

console.log(2)
// 输出结果:1,2,3,4

new Promise在实例化的过程中所执行的代码都是同步进行的,而then中注册的回调才是异步执行的。在同步代码执行完成后才回去检查是否有异步任务完成,并执行对应的回调,而微任务又会在宏任务之前执行。所以就得到了上面的输出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
*/

首先输出script start没问题,然后await async2()会把console.log('async2 end');放到new Promise里去执行,而把console.log('async1 end')放到.then里去,那么这个时候async2 end会先执行,然后按顺序执行Promise和script end ,通过微任务比宏任务先执行的原则,async1 end被打印,按顺序promise1和promise2被打印,最终宏任务settimeout被打印

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值