JS基础-异步/异步进阶(重要)-面试题

单线程和异步

JS是单线程语言,只能同时做一件事;浏览器和nodejs已支持JS启动进程,如Web Worker;JS和DOM渲染共用同一个线程,因为JS可修改DOM结构。

因此遇到等待(网络请求,定时任务)不能卡住,因此需要异步,异步是基于callback回调函数形式来调用

异步和同步

基于JS是单线程语言,异步不会阻塞代码的执行,而同步会阻塞代码的执行

应用场景

网络请求,如ajax图片加载;定时任务,如setTimeout

//图片加载
console.log('start')
let img = document.createElement('img')
img.onload = function() {
    console.logg('loaded')
}
img.src = '/xxx.png'
console.log('end')

callback hell(回调地狱)

Promise

初始化promise时(new Promise),传入的函数会立刻被执行

异步应用场景

网络请求,如ajax图片加载;定时任务,如setTimeout


event loop(事件循环/事件轮询)

由于JS是单线程运行的,异步要基于回调来实现,event loop就是异步回调的实现原理。异步(setTimeout,ajax等)使用回调,基于event loop,DOM事件也使用回调,基于event loop(但DOM事件不属于异步)

event loop过程:同步代码,一行一行放在Call Stack执行,直接执行;遇到异步,会先“记录”下,等待时机(定时、网络请求和事件触发等);时机到了,就移动到Callback Queue;如Call Stack为空(即同步代码执行完)Event Loop开始工作;轮询查找Callback Queue,如有则移动到Call Stack执行,然后继续轮询查找。(当Call Stack空闲,会尝试DOM渲染)

Promise

状态

有三种状态:pending(过程中)  resolved(已解决)  rejected(失败),只能从pending——>resolved/rejected,并且变化是不可逆的。

状态的表现

pending状态,不会触发then和catch;resolved状态,会触发后续的then回调函数;rejected状态,会触发后续的catch回调函数。

then和catch改变状态

then正常返回resolved,里面有报错则返回rejected;catch正常返回resolved,里面有报错则返回rejected。rejected触发catch回调,resolved触发then回调


async/await

通过同步的写法写异步的作用。还是解决异步回调callback hell的问题,虽然Promise then catch是链式调用,但也是基于回调函数。async/await是同步语法,可以彻底消灭回调函数。

async/await和Promise的关系

async/await是消灭异步回调的终极武器,但和Promise并不互斥,反而两者相辅相成。

执行async函数,返回的是Promise对象,await相当于Promise的then,try...catch可捕获异常,代替了Promise的catch。async是封装的Promise

async function fn1() {
    //return 100 //async自动讲这个封装成一个Promise对象,相当于return Promise.resolve(100)
    return Promise.resolve(200)
}

const res1 = fn1()  //执行async函数,返回的是一个Promise对象
console.log('res1',res1)  //promise对象
res1.then(data => {
    console.log('data',data) //100
})
---------------------------------------
!(async function () {
    const p1 = Promise.resolve(300)
    const data = await p1 // await相当于Promise then
    console.log('data',data)
})()
----
!(async function () {
    const data1 = await 400 // await Promise.resolve(400)
    console.log('data1',data1)
})()
----
!(async function () {
    const data2 = await fn1() // await Promise.resolve(400)
    console.log('data2',data2)
})()
----
!(async function () {
    const p4= Promise.reject('err1') // await Promise.resolve(400)//reject状态
    try {
        const res = await p4
        console.log(res)
    } catch (ex) {
        console.error(ex) // try...catch相当于promise catch
    }
})()// 注意await不能直接接reject

异步的本质

async function async(){
    console.log('async1 start') // 2
    await async2() //undefined
    //await的后面都可以看作是callback里的内容,即异步
    //类似,event loop,setTimeout()
    //setTimeout((function(){console.log('async1 end')})
    //Promise.resolve().then(() => {console.log('async1 end')}
    console.log('async1 end')//5
}

async function async2(){
    console.log('async2') //3
}

console.log('script start') //1
async1()  //与定时器等不同,这是函数调用,就直接回到函数定义的地方去执行了
console.log('script enf')//4
//同步代码已经执行完(event loop)
//结果为script start  async1 start  async2  script enf  async1 end

for...of

for...in(以及forEach for)是常规的同步遍历;for...of常用于异步的遍历


宏任务macroTask和微任务microTask

宏任务:setTimeout,setInterval,Ajax,DOM事件;微任务:Promise,async/await;微任务执行时机比宏任务要早。

event loop和DOM渲染

JS单线程,而且和DOM渲染共用一个线程;JS执行的时候,得留一些时机供DOM渲染

每次Call Stack清空(即每次轮询结束),即同步任务执行完都是DOM重新渲染的机会,DOM结构如有改变则重新渲染,然后再去触发下一次Event loop

 微任务和宏任务的区别

宏任务:DOM渲染后触发,如setTimeout;微任务:DOM渲染前触发,如Promise

微任务是ES6语法规定的,宏任务是由浏览器规定的。宏任务会放到Web APIs中而微任务不会

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值