EventLoop
# 1
const promise = new Promise((resolve, reject) => {
console.log(1)
resolve()
console.log(2)
})
promise.then(() => {
console.log(3)
})
console.log(4)
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');
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
详细答案
- 执行console.log('script start'),输出script start;
- 执行setTimeout,是一个异步动作,放入宏任务异步队列中;
- 执行async1(),输出async1 start,继续向下执行;
- 执行async2(),输出async2,并返回了一个promise对象,await让出了线程,把返回的promise加入了微任务异步队列,所以async1()下面的代码也要等待上面完成后继续执行;
- 执行 new Promise,输出promise1,然后将resolve放入微任务异步队列;
- 执行console.log('script end'),输出script end;
- 到此同步的代码就都执行完成了,然后去微任务异步队列里去获取任务
- 接下来执行resolve(async2返回的promise返回的),输出了async1 end。
- 然后执行resolve(new Promise的),输出了promise2。
- 最后执行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()
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}`)
}
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}`)
}
2
3
4
5
查看答案
添加await,将代码改成同步执行的。
PS: 最新的 Chrome 已经支持在全局作用域下使用 await 了,如果不行那么就在外层写一个async函数。
try {
await (async function() { a().b().c() })()
} catch (e) {
console.log(`执行出错:${e.message}`)
}
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)
}
2
3
4
5
6
7
8
9
10
11
查看答案
// inner 1
// outer 1
// 直接抛出错误 Uncaught (in promise) Error: 123
下面代码考察的点:
- async函数返回什么?async返回一个promise函数,里面的错误会进入reject
- 事件队列,宏任务和微任务的执行关系
- 闭包,作用域
- 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) // -> ?
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