EventLoop

3/22/2022 running

# 1

const promise = new Promise((resolve, reject) => {
    console.log(1)
    resolve()
    console.log(2)
})
promise.then(() => {
    console.log(3)
})
console.log(4)
1
2
3
4
5
6
7
8
9
查看答案

1
2
4
3

# 2

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('asnyc1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(() => {
    console.log('setTimeOut');
}, 0);
async1();
new Promise(function (reslove) {
    console.log('promise1');
    reslove();
}).then(function () {
    console.log('promise2');
})
console.log('script end');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
简单答案

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeOut

详细答案
  1. 执行console.log('script start'),输出script start;
  2. 执行setTimeout,是一个异步动作,放入宏任务异步队列中;
  3. 执行async1(),输出async1 start,继续向下执行;
  4. 执行async2(),输出async2,并返回了一个promise对象,await让出了线程,把返回的promise加入了微任务异步队列,所以async1()下面的代码也要等待上面完成后继续执行;
  5. 执行 new Promise,输出promise1,然后将resolve放入微任务异步队列;
  6. 执行console.log('script end'),输出script end;
  7. 到此同步的代码就都执行完成了,然后去微任务异步队列里去获取任务
  8. 接下来执行resolve(async2返回的promise返回的),输出了async1 end。
  9. 然后执行resolve(new Promise的),输出了promise2。
  10. 最后执行setTimeout,输出了settimeout。

# 3

下面的题在浏览器和node11以下输出的有什么不同?

function test () {
    console.log('start')
    setTimeout(() => {
        console.log('children2')
        Promise.resolve().then(() => {
            console.log('children2-1')
        })
    }, 0)
    setTimeout(() => {
        console.log('children3')
        Promise.resolve().then(() => {
            console.log('children3-1')
        })
    }, 0)
    Promise.resolve().then(() => {
        console.log('children1')
    })
    console.log('end')
}
test()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
查看答案

// 在 node11 及浏览器的执行结果(顺序执行宏任务和微任务)
start
end
children1
children2
children2-1
children3
children3-1

// 在 node11 以下版本的执行结果(先执行所有的宏任务,再执行微任务)
start
end
children1
children2
children3
children2-1
children3-1

# 4

下面代码执行输出什么?

try {
    (async function() { a().b().c() })()
} catch (e) {
    console.log(`执行出错:${e.message}`)
}
1
2
3
4
5
查看答案

// 直接抛出错误 Uncaught (in promise) ReferenceError: a is not defined 这道题目主要三个考点:

  • 执行一个没有定义的函数会发生什么
  • 在 async 内部发生报错会发生什么
  • try catch 只能捕获同步代码的异常

首先a执行没有定义,所以会抛出错误,其次在async里面,会说是在in promise中,第三因为async是异步函数,try-catch只能捕捉同步错误,所以不会走catch,会直接抛出系统错误。

# 5

下面代码如何修改,可以执行到catch里面

try {
    (async function() { a().b().c() })()
} catch (e) {
    console.log(`执行出错:${e.message}`)
}
1
2
3
4
5
查看答案

添加await,将代码改成同步执行的。
PS: 最新的 Chrome 已经支持在全局作用域下使用 await 了,如果不行那么就在外层写一个async函数。

try {
    await (async function() { a().b().c() })()
} catch (e) {
    console.log(`执行出错:${e.message}`)
}
1
2
3
4
5

# 6

下面代码输出什么?

try {
    let a = 0
    ;(async function() {
        a += 1
        console.log('inner', a)
        throw new Error('123')
    })()
    console.log('outer', a)
} catch(e) {
    console.warn('Error', e)
}
1
2
3
4
5
6
7
8
9
10
11
查看答案

// inner 1
// outer 1
// 直接抛出错误 Uncaught (in promise) Error: 123

下面代码考察的点:

  1. async函数返回什么?async返回一个promise函数,里面的错误会进入reject
  2. 事件队列,宏任务和微任务的执行关系
  3. 闭包,作用域
  • async内部函数是会先执行,在自调用函数中,因为a变量没有重新声明,那么是用上一级变量a,将变量变成1,之后直接输出inner 1
  • 执行到throw之后,抛出的错误会进入async的reject中,并进入微任务队列等待执行
  • 宏任务还没有执行完成,会执行outer 1 ,此时a已经变成了1
  • 之后执行微任务,因为try-catch只能捕获同步异常,所以无法捕获微任务错误,会直接抛出错误in promise Error: 123

# 7

下面代码输出什么?

var a = 0
var b = async () => {
  a = a + await 10
  console.log('2', a) // -> ?
}
b()
a++
console.log('1', a) // -> ?
1
2
3
4
5
6
7
8
查看答案

// 1 1
// 2 10

  • 首先执行b函数,从左到右进行加法运算,所以此时a锁定为0,遇到await之后,进入微任务队列
  • 此时执行a++,a增为1,打印出来 1 1
  • 这时宏任务执行完毕要执行微任务,a等于0+10=10,所以打印2 10

如果想要打印11怎么办?

将await10放在加法的前面 a = await 10 + a

更新时间: 2022-04-10 13:23