试题
1、执行顺序
const promise = new Promise((resolve, reject) => {
console.log(1)
resolve()
console.log(2)
})
promise.then(() => {
console.log(3)
})
console.log(4)
解析:
Promise 新建后就会立即执行。
new Promise构造函数是同步执行的。故先打印1,2;then是异步执行的,故先打印4,然后才打印3。
结果:1243
扩展
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve(5);
console.log(2);
}).then(val => {
console.log(val);
});
promise.then(() => {
console.log(3);
});
console.log(4);
setTimeout(function() {
console.log(6);
});
解析:promise是微观任务,setTimeout是宏观任务,先执行微观任务,再执行宏观任务;微观任务里,先执行同步再执行异步。这里的微任务队列为:先添加的promise.resolve(5).then((val)=>{console.log(val)}),后添加的promise.then(() => {
console.log(3)};
结果:124536
2、执行顺序
const first = () => (new Promise((resolve, reject) => {
console.log(3); //3
let p = new Promise((resolve, reject) => {
console.log(7); //37
setTimeout(() => { //放入下一轮队列
console.log(5);
resolve(6);
}, 0)
resolve(1);
});
resolve(2);
p.then((arg) => { //then1 放入微任务队列 arg = 1
console.log(arg);
});
}));
first().then((arg) => { //then2 放入微任务队列 arg = 2
console.log(arg);
});
console.log(4); //374
//执行微任务队列then1,得到3741,执行then2,得到37412,执行下一队列中的setTimeout,得到374125
结果:374125
3、resolve和reject
const promise = new Promise((resolve, reject) => {
resolve('success1') // pending->fulfilled, 状态一旦改变不能再改
reject('error')
resolve('success2')
})
promise
.then((res) => {
console.log('then: ', res) // then: success1
})
.catch((err) => {
console.log('catch: ', err)
})
4、then和catch
Promise.resolve(1)
.then((res) => {
console.log(res) //1
return 2
})
.catch((err) => {
return 3
})
.then((res) => {
console.log(res) //链式调用 //2
})
5、then和catch
Promise.resolve()
.then(() => {
return new Error('error!!!') //等价于 return Promise.resolve(new Error('error!!!'))
})
.then((res) => {
console.log('then: ', res) // then: Error: error!!! at <anonymous>
})
.catch((err) => {
console.log('catch: ', err)
})
解析:then 或者 catch 中 return 一个 error 对象并不会抛出错误,所以不会被后续的 .catch 捕获。可以使用以下方式被catch捕获。
return Promise.reject(new Error('error!!!'))
//或者
throw new Error('error!!!')
6、死循环
const promise = Promise.resolve()
.then(() => {
return promise
})
promise.catch(console.error)
// TypeError: Chaining cycle detected for promise #<Promise>
7、值穿透
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log) //“1”穿透上面两个then(Promise),到达这里成为实参
解析:then 或者catch 的参数期望是函数,传入非函数则会发生值穿透。
Promise.resolve(1).then(Promise.resolve(2)).then((v) => {
console.log(v)
}) // 1
Promise.resolve(1).then(return Promise.resolve(2)).then((v) => {
console.log(v)
}) //Uncaught SyntaxError: Unexpected token return;
Promise.resolve(1).then(null).then((v) => {
console.log(v)
})// 1
Promise.resolve(1).then(return 2).then((v) => {
console.log(v)
})// Uncaught SyntaxError: Unexpected token return;
Promise.resolve(1).then(() => {
return 2
}).then((v) => {
console.log(v) // 2
})
8、捕获错误
Promise.resolve()
.then(function success (res) {
throw new Error('error')
}, function fail1 (e) {
console.error('fail1: ', e)
})
.catch(function fail2 (e) {
console.error('fail2: ', e) // fail2: Error
})
解析:then有两个参数,写法为then(function(resolve){}, function(reject){}),catch是then的第二个参数的简写。注意:同一个then中第二个参数无法捕获第一个参数抛出的错误。
//上面例子写法等价于
Promise.resolve()
.then(function success1 (res) {
throw new Error('error')
}, function fail1 (e) {
console.error('fail1: ', e)
})
.then(function success2 (res) {
}, function fail2 (e) {
console.error('fail2: ', e)
})