- 执行async函数,返回的都是Promise对象
async function test1(){
return 1
}
async function test2(){
return Promise.resolve(2)
}
const result1 = test1()
const result2 = test2()
console.log('result1',result1)
console.log('result2',result2)
test1().then((a)=>{
console.log(a)
})
test2().then((a)=>{
console.log(a)
})
- Promise.then 成功的情况对应 await
async function test3(){
const p3 = Promise.resolve(3)
p3.then(data=>{
console.log('data',data)
})
const data = await p3
console.log('data',data)
}
test3()
async function test4(){
const data = await 4;// await Promise.resolve(4)
console.log('data',data)
}
test4()
async function test1(){
return 1
}
async function test5(){
const data = await test1()
console.log('data',data)
}
test5()
- Promise.catch 异常的情况对应 对应 try ...catch
async function test6(){
async function p(){
return Promise.reject(6)
}
p().catch((err)=>{
console.log('err1 '+err)
})
const p1 = p()
const p2 = Promise.reject(7)
p2.catch((err)=>{
console.log('err2 '+err)
})
try{
const data6 = await p2
const data7 = await p1()
console.log(p1)
console.log(p2)
}catch(err){
console.log('err '+err)
}
}
test6()
一些面试题
面试题1
async function async1() {
console.log("async1_start_2");
await async2();
console.log("async1_end_6");
return 'async_return_8';
}
async function async2() {
console.log("async2_3");
}
console.log("script_start_1");
setTimeout(function() {
console.log("setTimeout_9");
}, 0);
async1().then(function (message) { console.log(message) });
new Promise(function(resolve) {
console.log("promise_4");
resolve();
}).then(function() {
console.log("promise_7");
});
console.log("script_end_5");
这道题目考查的是我们对 事件循环 任务队列 的理解:
事件循环(Event Loop):
- JS会首先判断代码是同步还是异步,同步进入主线程,异步进入任务队列;
- 同步任务进入主线程后一直执行,直到主线程空闲后,才会去任务队列中查看是否有可执行的异步任务,如果有就推入主线程中执行;
- 事件循环是一个先进先出(FIFO)队列,这说明回调是按照它们被加入队列的顺序执行的。
分析:
-
在单线程的js中,异步代码会被放入一个事件队列,等到所有其他代码执行后再执行,而不会阻塞线程。 我们从上到下看,首先打印:
1; -
setTimeout / setInterval 要放到任务队列的末尾,等待后续执行。继续往下走;
此时的任务队列:
- 宏任务队列: setTimeout
- 微任务队列:none
-
async1 开始执行,当函数里遇到await时,暂停执行(await所在行放在本次执行完),而 async1 函数 未完成部分被添加到宏任务队列;
此时的任务队列:
- 宏任务队列:async1, setTimeout
- 微任务队列:none
-
new Promise() 实例对象被new出来后,它里面的promise1会立刻打印,然后又遇到 then, 此时 promise 实例 被添加到微任务队列;
此时的任务队列:
- 宏任务队列:async1 ,setTimeout
- 微任务队列: promise实例
- 接着打印:script end。至此,同步代码(第一个宏任务)已执行完毕。而我们的任务队列中还存在着 async1, promise对象, setTimeout异步回调;
- 由于异步代码第一次执行时,async1 函数 要早于 promise对象,所以紧接着 async1 函数继续执行没有执行完成的部分(例三中promise.then先于await,所以then先执行),执行完毕后,退出任务队列,打印:async1 end。然后把它的 then 逻辑添加到任务微任务队列中;
此时的任务队列:
- 宏任务队列:setTimeout
- 微任务队列:promise实例 ,async1的then逻辑部分
- 先清空微任务队列,promise 实例 继续执行它的 then 的逻辑,打印:promise2。执行完毕后,退出微任务队列;
此时的任务队列:
- 宏任务队列:setTimeout
- 微任务队列:async1的then逻辑部分
- async 函数执行 then 逻辑;
此时的任务队列:
- 宏任务队列:setTimeout
- 微任务队列:none
- setTimeout是宏任务会在最后执行。
面试题2
console.log(1);
async function asyncfn1(){
console.log(2);
await asyncfn2();
console.log(5);
};
setTimeout(() => {
console.log('setTimeout')
}, 0)
async function asyncfn2(){
console.log(3)
};
asyncfn1();
console.log(4);
分析
1 . 首先执行全局同步代码,先输出 1
2 . 随后执行asyncfn1,输出 2 遇到awati后,先执行asyncfn2,将后面的代码放入宏任务队列,
此时的任务队列:
- 宏任务队列:
asyncfn1剩余代码; - 微任务队列:none;
- 执行
asyncfn2输出3; - 继续执行全局同步代码,输出
4; - 执行宏任务输出
5;
面试题三
var p = new Promise((res,rej) => {
res('hello_6')
console.log('1')
})
function hello() {
console.log('hello_begins_2')
return p
}
hello().then(res => {
console.log(res)
console.log('hello_7')
return 'hello_10'
}).then(res => {
console.log(res)
console.log('hello_11')
return 'hello_13'
}).then(res => {
console.log(res)
console.log('hello_14')
})
function test1 () {
console.log('test1_5')
}
async function asy () {
console.log('asy_begins_3')
await console.log('asy_4')
console.log('async_8')
await console.log('asy_9')
console.log('asy_ends_12')
}
asy()
test1()
注意: await后面的代码虽然算作宏任务,但是和普通的微任务不在一个维度,位于更上一层的任务队列,所以优先度要比其他(下层)微任务要高;
参考思路:
- 执行同步的全局代码输出
1(遇到new Promise()的需要立即执行) - 第
11行执行hello函数,输出2,并返回一个Promise对象p,将hello函数的第一层then函数放入微任务队列;
此时的任务队列:
- 宏任务队列:none
- 微任务队列:hello.then(0)
- 继续执行同步代码,到第
38行,执行asy函数; - 在第
29行输出3,随后遇到await,执行该行,输出4,剩下的代码被放入了宏任务队列(为了区分任务的层次,标明了序号,先执行完同层的任务,再到其他层)
此时的任务队列:
- 宏任务队列:asy await后代码(0)
- 微任务队列:hello.then(0),hello.then.then(1),hello.then.then.then(2)
- 继续执行同步全局代码,第40行,执行test函数,输出
5; - 执行微任务队列中的hello.then,输出返回的promise对象p中的处理结果
6(第12->8->2行),随后第13行输出7;
此时的任务队列:
- 宏任务队列:asy await后代码(0)
- 微任务队列:hello.then.then(1),hello.then.then.then(2)
- 执行第0层的宏任务,也就是asy await后的代码,第
32行输出8,第39行遇到await,执行完该行输出9后,将后面的代码推进宏任务队列;
此时的任务队列:
- 宏任务队列:asy await后代码(1)
- 微任务队列:hello.then.then(1),hello.then.then.then(2)
- 第
15行,执行hello函数的第二个then函数,返回处理结果res,输出10和11;
此时的任务队列:
- 宏任务队列:asy await后代码(1)
- 微任务队列:hello.then.then.then(2)
- 同层的还有一个宏任务,执行asy await后的代码,第
35行,输出12;
此时的任务队列:
- 宏任务队列:none
- 微任务队列:hello.then.then.then(2)
- 取出微任务队列中的最后一个任务,回到第
19行输出hello的第二个then函数的处理结果,分别是13和14;
至此程序执行完成;