聊聊前端面试之输出顺序

栏目: JavaScript · 发布时间: 5年前

内容简介:春节后,新一轮跳槽风暴不知道能否吹暖今冬的裁员寒冬。然而,职场现状就是越来越多的小公司也在效仿各大互联网牛场面试要求,对于底层知识要求越来越深,管他用着用不着的,先面了再说。本篇跟大家聊聊面试常见题型之显示顺序问题。注:本篇分析为在浏览器环境中排序显示。Nodejs编程是全异步,事件引擎为libuv。

春节后,新一轮跳槽风暴不知道能否吹暖今冬的裁员寒冬。然而,职场现状就是越来越多的小公司也在效仿各大互联网牛场面试要求,对于底层知识要求越来越深,管他用着用不着的,先面了再说。本篇跟大家聊聊面试常见题型之显示顺序问题。

注:本篇分析为在浏览器环境中 排序 显示。

Nodejs编程是全异步,事件引擎为libuv。

一、JavaScript运行机制

关于运行机制聊四个关键点:

  • 单线程:同一时间只能解决一件事,是JS核心特征。JS为什么不能多线程?因为JS是浏览器脚本语言,主要用于用户交互与DOM操作;
  • 任务类型: 同步任务异步任务 。同步任务是主线程上的排队等待解决的任务,只有完成一项任务,才可以进行下一个任务;异常任务,不进入主线程任务,而是进入“任务队列”,只有主线程的任务完成后,才会召唤“任务队列”上任务并执行;
  • 任务队列:是一个事件队列,I/O设备完成一项任务,就会在“任务队列”里添加一个事件。 注意,必须I/O设备完成有结果,才会进入到“任务队列”;
  • 事件循环(Event Loop):主线程不断的循环从“任务队列”读取事件的运行机制。

二、任务的阶级斗争

JavaScript任务运行机制图

第一阶级:同步任务

1、皇帝豪饮两碗鹿血,问有个叫EventLoop的公公,今晚谁来陪睡,EventLoop掐指一算,正宫几个“同步任务“娘娘都送过礼,我就按照送礼顺序来给她们安排吧。

同步任务优先执行,先进先出。

第二阶级:异步任务(微任务)

2、几晚过后,所有送过礼的“同步任务”娘娘轮流服侍皇帝一遍。如此同时,秀宫的宫女们忙着化妆整容。原来,宫里有个不成文的规定,只有收拾好自己的宫女才可以排队等待皇帝的召唤,到时候公公EventLoop会按照排队次序向皇帝安排服侍。

3、什么时候才轮到宫女们服侍呢?是“同步任务”娘娘们服侍一遍后,毕竟公公EventLoop为了保护自己的饭碗,得让皇帝不断尝鲜。

同步任务执行的同时,异步任务在事件栈完成后,异步任务进入“任务队列”;

事件循环(Event Loop)驱使主线程在全部同步任务完成后,从“任务队列”读取事件,如此不断循环;

任务队列执行先进先出;

第三阶级:异步任务--定时器(宏任务)

4、在秀宫有两个宫女姓SetTimeout和setInterval,人老珠黄,虽然化妆技术还可以,也送过了礼,无奈确实不上档次,负责秀宫的公公就让她俩排在了所有宫女的后边,等着呗。

5、这俩宫女终于看到希望了,可谁知又来一批年轻漂亮的秀女,怎么办,等着呗。

6、终于,前前后后好几批年轻秀丽的宫女们服侍完皇帝,轮到这两位了,按照老规则,谁先来的谁优先,俩人对视苦笑,回头一看,又来几个姓SetTimeout和setInterval的宫女...

同时嵌套在异步操作的任务,会将嵌套在异步的下一次任务队列中;

定时器任务添加到任务队列的尾部;

三、案例分析

基于今日头条的面试题改造

async function async1() {
    console.log(1)
    await async2()
    console.log(2)
    return await 3
}
async function async2() {
    console.log(4)
}

setTimeout(function() {
    console.log(5)
}, 0)

async1().then(v => console.log(v))
new Promise(function(resolve) {
    console.log(6)
    resolve();
    console.log(7)
}).then(function() {
    console.log(8)
})
console.log(9)复制代码
  • 从代码第一行开始,异步函数async1、async2构建完未执行。
  • 按照代码顺序,首先该执行的应该是 setTimeout ,怎奈又不是正宫,长得又不秀丽,只能在任务队列最后等着。
  • 运行到 async1.then() 时,async1返回一个 Promise 对象(异步函数其实是封装的 Promise.resolve()Promise 对象是一个构造函数),所以在执行async1时,首先将非resolve、reject函数加入主线程,上题中首先执行 console.log(1)await async2

    输出 1,4 。感觉await挺孙子的,执行完自己的函数就跳出来 async

    函数。

  • 继续看,异步函数async1的then执行这个时候进入事件栈,因为还在等待异步函数async1返回值,等着吧。
  • 继续向下执行遇到真正的 Promise 对象了,二话不说,执行下先, console.log(6)console.log(7) 直接加入到主线程,输出 6,7 。同时将异步函数console.log(8)放在储秀宫,虽然属于第二阶级,起码还是第二阶级的老大么。
  • 单纯的console.log(9)说,咱也是第一阶级的,虽然最后一位,侍架一晚,输出了

    9

  • 同步人物结束了,Event Loop开始召唤任务队列,console.log(8)说我是秀女中的第一位,好,就你了。于是,生出了 8
  • setTimeout翘首以盼,谁知,执行完本轮又跳到到异步函数async1,率先看到了 console.log(2) ,所以输出了 2
  • 紧接着,又遇到了 await 了,还好,结束了,返回的值扔给了 async 的异步函数,得到了值,抓紧时间执行,得到结果了,终于可以进入任务队列,这时主线程也是空的,执行下结果吧,输出了 3
  • 所有微任务结束了,该宏任务大展拳脚了,setTimeout输出了值, 5

以上试题分析完毕,输出结果顺序为: 1,4,6,7,9,8,2,3,5

四、最后

以上是个人对于任务执行顺序的理解,如理解有误,希望大神多多指教。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Making Things See

Making Things See

Greg Borenstein / Make / 2012-2-3 / USD 39.99

Welcome to the Vision Revolution. With Microsoft's Kinect leading the way, you can now use 3D computer vision technology to build digital 3D models of people and objects that you can manipulate with g......一起来看看 《Making Things See》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具