Fe-interview: Day28:写出执行结果,并解释原因(以最新谷歌浏览器为准)

Created on 22 Jun 2020  ·  4Comments  ·  Source: lgwebdream/FE-Interview

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(function() {
    console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');

每日一题会在下午四点在交流群集中讨论,五点小程序中更新答案
欢迎大家在下方发表自己的优质见解
二维码加载失败可点击 小程序二维码

扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。

Most helpful comment

答案:
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

解析:

知识点:
考察的是js中的事件循环和回调队列。注意以下几点

  • 1.Promise优先于setTimeout宏任务。所以,setTimeout回调会在最后执行。
  • 2.Promise一旦被定义,就会立即执行
  • 3.Promiserejectresolve是异步执行的回调。所以,resolve()会被放到回调队列中,在主函数执行完和setTimeout前调用。
  • 4.await执行完后,会让出线程。async标记的函数会返回一个Promise对象

迷惑点

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
// 相当于
function async1() {
    return new Promise((resolve,reject)=>{
        console.log('async1 start');
        async2().then((result)=>{
            console.log('async1 end');
        })
       resolve()
    })
}
function async2() {
    return new Promise((resolve)=>{
        console.log('async2');
        resolve()
    })
}

执行流程分析

  • 1.首先,事件循环从宏任务(macrotask)队列开始,这个时候,宏任务队列中,只有一个script(整体代码)任务;从宏任务队列中取一个任务出来执行。

    • a.首先执行console.log('script start') ,输出 'script start' 。

    • b.遇到setTimeout 把 console.log('setTimeout') 放到macroTask队列中。

    • c.执行async1(), 输出 'async1 start' 和 'async2' ,把 console.log('async1 end') 放到micro 队列中。

    • d.执行到promise , 输出 'promise1' , 把 console.log('promise2') 放到micro 队列中。

    • e.执行 console.log('script end') 。输出 'script end'

  • 2.macrotask 执行完会执行microtask ,把 microtask quene 里面的 microtask 全部拿出来一次性执行完,所以会输出 ‘async1 end’ 和 ‘ promise2’
  • 3.开始新一轮事件循环,去除一个macrotask执行,所以会输出 “setTimeout”。

All 4 comments

答案:
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

解析:

知识点:
考察的是js中的事件循环和回调队列。注意以下几点

  • 1.Promise优先于setTimeout宏任务。所以,setTimeout回调会在最后执行。
  • 2.Promise一旦被定义,就会立即执行
  • 3.Promiserejectresolve是异步执行的回调。所以,resolve()会被放到回调队列中,在主函数执行完和setTimeout前调用。
  • 4.await执行完后,会让出线程。async标记的函数会返回一个Promise对象

迷惑点

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
// 相当于
function async1() {
    return new Promise((resolve,reject)=>{
        console.log('async1 start');
        async2().then((result)=>{
            console.log('async1 end');
        })
       resolve()
    })
}
function async2() {
    return new Promise((resolve)=>{
        console.log('async2');
        resolve()
    })
}

执行流程分析

  • 1.首先,事件循环从宏任务(macrotask)队列开始,这个时候,宏任务队列中,只有一个script(整体代码)任务;从宏任务队列中取一个任务出来执行。

    • a.首先执行console.log('script start') ,输出 'script start' 。

    • b.遇到setTimeout 把 console.log('setTimeout') 放到macroTask队列中。

    • c.执行async1(), 输出 'async1 start' 和 'async2' ,把 console.log('async1 end') 放到micro 队列中。

    • d.执行到promise , 输出 'promise1' , 把 console.log('promise2') 放到micro 队列中。

    • e.执行 console.log('script end') 。输出 'script end'

  • 2.macrotask 执行完会执行microtask ,把 microtask quene 里面的 microtask 全部拿出来一次性执行完,所以会输出 ‘async1 end’ 和 ‘ promise2’
  • 3.开始新一轮事件循环,去除一个macrotask执行,所以会输出 “setTimeout”。

console.log('async1 start');
async1().then((result)=>{
console.log('async1 end');
})
这一块写错了吧,async2()写成async1()了

console.log('async1 start');
async1().then((result)=>{
console.log('async1 end');
})
这一块写错了吧,async2()写成async1()了

@yaokangsong 感谢指正Thanks♪(・ω・)ノ,答案已修正

给大家出个题,把第3行的await去掉,输出的结果会变成什么?

Was this page helpful?
0 / 5 - 0 ratings