异步&事件循环____代码输出题
一、Promise
1.
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})
const promise2 = promise1.then(() => {
throw new Error('error!!!')
})
console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() => {
console.log('promise1', promise1)
console.log('promise2', promise2)
}, 2000)
答案:
promise1 Promise {
}
promise2 Promise {} Uncaught (in promise) Error: error!!!
promise1 Promise {: "success"}
promise2 Promise {: Error: error!!} throw 抛出错误,会使Promise状态变为Rejected。
2.
Promise.resolve().then(() => {
return new Error('error!!!')
}).then(res => {
console.log("then: ", res)
}).catch(err => {
console.log("catch: ", err)
})
答案:
"then: " "Error: error!!!"
返回任意一个非 promise 的值都会被包裹成 promise 对象,因此这里的
return new Error('error!!!')
也被包裹成了return Promise.resolve(new Error('error!!!'))
,因此它会被then捕获而不是catch。
3.
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
答案: 1
只需要记住一个原则:
.then
或.catch
的参数期望是函数,传入非函数则会发生值透传。第一个then和第二个then中传入的都不是函数,一个是数字,一个是对象,因此发生了透传,将
resolve(1)
的值直接传到最后一个then里,直接打印出1。
4.
Promise.resolve('1')
.then(res => {
console.log(res)
})
.finally(() => {
console.log('finally')
})
Promise.resolve('2')
.finally(() => {
console.log('finally2')
return '我是finally2返回的值'
})
.then(res => {
console.log('finally2后面的then函数', res)
})
答案: 1、finally2、finally、finally2后面的then函数 2。
.finally()
一般用的很少,只要记住以下几点就可以了:
.finally()
方法不管Promise对象最后的状态如何都会执行.finally()
方法的回调函数不接受任何的参数,也就是说你在.finally()
函数中是无法知道Promise最终的状态是resolved
还是rejected
的- 它最终返回的默认会是一个上一次的Promise对象值,不过如果抛出的是一个异常则返回异常的Promise对象。
- finally本质上是then方法的特例
Promise.resolve('1')
.finally(() => {
console.log('finally1')
throw new Error('我是finally中抛出的异常')
})
.then(res => {
console.log('finally后面的then函数', res)
})
.catch(err => {
console.log('捕获错误', err)
})
答案: finally1 、'捕获错误' Error: 我是finally中抛出的异常
5.
const first = () => (new Promise((resolve, reject) => {
console.log(3);
let p = new Promise((resolve, reject) => {
console.log(7);
setTimeout(() => {
console.log(5);
resolve(6);
console.log(p)
}, 0)
resolve(1);
});
resolve(2);
p.then((arg) => {
console.log(arg);
});
}));
first().then((arg) => {
console.log(arg);
});
console.log(4);
答案:3、7、4、1、2、5、Promise{
: 1}
6.
Promise.resolve().then(() => {
console.log('promise1');
const timer2 = setTimeout(() => {
console.log('timer2')
}, 0)
});
const timer1 = setTimeout(() => {
console.log('timer1')
Promise.resolve().then(() => {
console.log('promise2')
})
}, 0)
console.log('start');
答案:start、promise1、timer1、promise2、timer2
二、async/await
1.
async function a() {
console.log(await Promise.resolve('3'));
}
async function b() {
console.log(await '2');
}
async function c() {
console.log('1');
}
b();
a();
c();
答案:1、2、3;
切换调用 b函数和 a 函数的顺序,则输出1、3、2。
2.
async function foo() {
console.log(2);
console.log(await Promise.resolve(8));
console.log(9);
}
async function bar() {
console.log(4);
console.log(await 6);
console.log(7);
}
console.log(1);
foo();
console.log(3);
bar();
console.log(5);
答案:1、2、3、4、5、8、9、6、7。
3.
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
setTimeout(() => {
console.log('timer1')
}, 0)
}
async function async2() {
setTimeout(() => {
console.log('timer2')
}, 0)
console.log("async2");
}
async1();
setTimeout(() => {
console.log('timer3')
}, 0)
console.log("start")
答案:async1 start、async2、start、async1 end、timer2、timer3、timer1
代码的执行过程如下:
- 首先进入
async1
,打印出async1 start
;- 之后遇到
async2
,进入async2
,遇到定时器timer2
,加入宏任务队列,之后打印async2
;- 由于
async2
阻塞了后面代码的执行(后面的代码都加入微任务队列),所以执行后面的定时器timer3
,将其加入宏任务队列,之后打印start
;- 然后执行async2后面的代码,打印出
async1 end
,遇到定时器timer1,将其加入宏任务队列;- 最后,宏任务队列有三个任务,先后顺序为
timer2
,timer3
,timer1
,没有微任务,所以直接所有的宏任务按照先进先出的原则执行。
4.
async function async1 () {
console.log('async1 start');
await new Promise(resolve => {
console.log('promise1')
})
console.log('async1 success');
return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')
答案:script start、async1 start、promise1、script end
注意:
在
async1
中await
后面的 Promise 是没有返回值的,也就是它的状态始终是pending
状态,所以在await
之后的内容是不会执行的,包括async1
后面的.then
。
5.
async function async1 () {
await async2();
console.log('async1');
return 'async1 success'
}
async function async2 () {
return new Promise((resolve, reject) => {
console.log('async2')
reject('error')
})
}
async1().then(res => console.log(res))
答案:async2、Uncaught (in promise) error
如果async函数中抛出了错误,就会终止错误结果,不会继续向下执行。
三、综合异步、事件循环
1.
async function async1() {
console.log(1)
await async2();
console.log(2);
}
async function async2() {
console.log(3)
}
console.log(4)
setTimeout(function () {
console.log(5)
}, 0)
new Promise(function (resolve) {
console.log(6)// 同步
resolve()
}).then(function () {
console.log(7)//异步
})
async1()
console.log(8)
答案:4、6、1、3、8、7、2、5
2.
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(resolve => {
console.log("promise1");
resolve();
}).then(function() {
console.log("promise2");
});
console.log('script end')
答案:script start、async1 start、async2、promise1、script end、async1 end、promise2、setTimeout
3.
const async1 = async () => {
console.log('async1');
setTimeout(() => {
console.log('timer1')
}, 2000)
await new Promise(resolve => {
console.log('promise1')
})
console.log('async1 end')
return 'async1 success'
}
console.log('script start');
async1().then(res => console.log(res));
console.log('script end');
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.catch(4)
.then(res => console.log(res))
setTimeout(() => {
console.log('timer2')
}, 1000)
答案:script startasync1、promise1、script end、1、timer2、timer1
4.
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
答案:1、7、6、8、2、4、3、5、9、11、10、12。
注意:
执行一次宏任务队列的任务后,就得清空微任务队列!
,这就是为什么2、4后输出3和5的原因。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律