复习梳理一:Promise
定义
promise是异步编程的一种解决方案。是一个微任务。
2个特点
(1)对象的状态不受外界影响。(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。
3个状态
pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
优点
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
缺点
Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
Promise考点
- Promise 新建后就会立即执行.
- 调用
resolve或reject并不会终结 Promise 的参数函数的执行. - Promise 状态已经变成
resolved,再抛出错误是无效的 finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果- promise.all 场景。如果作为参数的 Promise 实例,自己定义了
catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法 - 立即
resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时 - .then和.catch都会返回一个新的
Promise
promise的API
then()
catch()
finally()
all()
race()
allSettled()
any()
resolve()
reject()
try()
刷题
题1
考点:Promise 新建后就会立即执行
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// resolved.
题2
考点:调用
resolve或reject并不会终结 Promise 的参数函数的执行
new Promise((resolve, reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
// 2
// 1
补充:一般来说,调用resolve或reject以后,Promise 的使命就完成了,后继操作应该放到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加上return语句,这样就不会有意外。
const p = new Promise((resolve, reject) => {
return resolve(1);
// 后面的语句不会执行
console.log(2);
})
console.log(3);
// 3
// 1
题3
考点:Promise 状态已经变成
resolved,再抛出错误是无效的
const promise = new Promise(function(resolve, reject) {
resolve('ok');
throw new Error('test'); // 无效
});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });
// ok
题4
考点:如果作为参数的 Promise 实例,自己定义了
catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e); // 自己定义了catch
Promise.all([p1, p2])
.then(result => console.log(result)) // 走这里
.catch(e => console.log(e));
// ['hello', 'Error 报错了']
如果p2没有自己的catch方法,就会调用Promise.all()的catch方法。
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// Error: 报错了
题5:
考点:立即
resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
// one
// two
// three
题5
考点:Promise 新建后就会立即执行。
promise1没有被resolve或者reject,因此状态还是pending
const promise1 = new Promise((resolve, reject) => {
console.log('promise1')
})
console.log('1', promise1);
// promise1
// 1 Promise{<Pending>}
题6
考点:promise的状态可有resolve和reject决定。同步任务和异步任务的执行顺序。
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve('success')// 返回了resolve,在后面的then中就能执行
console.log(2);
});
promise.then(() => {
console.log(3);
});
console.log(4);
// 1
// 2
// 4
// 3
题7
考点:在
promise中并没有resolve或者reject.因此promise.then并不会执行,它只有在被改变了状态之后才会执行
const promise = new Promise((resolve, reject) => {
console.log(1);
console.log(2);
// 没有resolve返回,仍处于pending状态,不进入.then
});
promise.then(() => {
console.log(3);
});
console.log(4);
// 1
// 2
// 4
题8
考点:promise实例返回格式,微任务队列执行顺序,promise改变状态的时机
const promise1 = new Promise((resolve, reject) => {
console.log('promise1') // 新建promise,立即执行
resolve('resolve1') // 将promise1的状态改成resolved,并将结果保存下来
})
const promise2 = promise1.then(res => { // promise1.then 放入微任务队列
console.log(res)
// 无resolve和reject 状态为pending的新的promise
})
console.log('1', promise1); // 立即执行同步任务,拿到promise1的状态
console.log('2', promise2);// 立即执行同步任务,拿到promise2的状态
// 将微任务队列的结果返回
// promise1
// 1,Promise{<Resolved>: 'resolve1'}
// 2,Promise{<Pending>}
// resolve1
题9
考点:
fn函数它是直接返回了一个new Promise的,而且fn函数的调用是在start之前,所以它里面的内容应该会先执行。
const fn = () => (new Promise((resolve, reject) => {
console.log(1);
resolve('success')
})) // 一个函数,1 先打印
fn().then(res => { // 函数被调用了
console.log(res)
})
console.log('start')
// 1
// start
// success
题10
考点:Promise 新建后就会立即执行。注意它是不是被包裹在函数当中,如果是的话,只有在函数调用的时候才会执行。
const fn = () =>
new Promise((resolve, reject) => {
console.log(1);
resolve("success");
});
console.log("start");
fn().then(res => {
console.log(res);
});
// start
// 1
// success
题11
考点:宏任务与微任务的执行顺序。
console.log('start') // 宏任务
setTimeout(() => { // 下一个宏任务队列执行
console.log('time')
})
Promise.resolve().then(() => {
console.log('resolve') // 微任务
})
console.log('end') // 宏任务
// start
// end
// resolve
// time
题12
const promise = new Promise((resolve, reject) => {
console.log(1); // 立即执行宏任务打印
setTimeout(() => { // 定时器,放入下一个宏任务的延迟队列中等待执行
console.log("timerStart");
resolve("success");
console.log("timerEnd");
}, 0);
console.log(2); // 执行,resolve即使调用了也不会终止
});
promise.then((res) => { // 微任务,其状态还是为pending,这里理解为先不执行。依赖定时器的结果
console.log(res);
});
console.log(4); // 立即执行
// 一轮循环过后,进入第二次宏任务,发现延迟队列中有setTimeout定时器,执行定时器的内容
// 1
// 2
// 4
// timerStart
// timerEnd
// success
题13
考点:promise.then()是微任务,在本轮宏仁务执行完后,执行其存在的微任务队列。setTimeout宏仁务,但再下一轮宏仁务队列中执行。
setTimeout(() => {
console.log('timer1');
setTimeout(() => { // 定时器timer3的话,它会在timer2后执行
console.log('timer3')
}, 0)
}, 0)
setTimeout(() => {
console.log('timer2')
}, 0)
console.log('start')
// start
// timer1
// timer2
// timer3
setTimeout(() => {
console.log('timer1');
Promise.resolve().then(() => { // Promise.then却是在timer2之前执行
console.log('promise')
})
}, 0)
setTimeout(() => {
console.log('timer2')
}, 0)
console.log('start')
// start
// timer1
// promise
// timer2
题14
Promise.resolve().then(() => { // 放入本轮微任务队列1
console.log('promise1'); // 宏仁务2
const timer2 = setTimeout(() => { // 下一次宏仁务3,等待执行
console.log('timer2')
}, 0)
});
const timer1 = setTimeout(() => {
console.log('timer1') // 立即执行
Promise.resolve().then(() => { // 下一次宏仁务执行,在执行下一次微任务队列
console.log('promise2')
})
}, 0)
console.log('start');// 本轮宏仁务1立即执行
// start
// promise1
// timer1
// promise2
// timer2
题15
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => { // 放入下一轮,宏2
resolve('success')
}, 1000)
})
const promise2 = promise1.then(() => { // 微任务,状态为pending,等待执行
throw new Error('error!!!')
})
console.log('promise1', promise1)// 立即执行,打印
console.log('promise2', promise2)// 立即执行,打印
setTimeout(() => { // 放入下一轮,宏3
console.log('promise1', promise1)
console.log('promise2', promise2)
}, 2000)
// promise1,Promise{<Pending>}
// promise2,Promise{<Pending>} 会报错
// promise1,Promise{<fulfilled>: "success"}
// promise2,Promise{<rejected>: Error: error!!!}
题16
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success");
console.log("timer1");
}, 1000);
console.log("promise1里的内容");
});
const promise2 = promise1.then(() => {
throw new Error("error!!!");
});
console.log("promise1", promise1);
console.log("promise2", promise2);
setTimeout(() => {
console.log("timer2");
console.log("promise1", promise1);
console.log("promise2", promise2);
}, 2000);
// promise1里的内容
// promise1, Promise{<Pending>}
// promise2, Promise{<Pending>}
// timer1
// 报错 Uncaught (in promise) Error: error!!!
// timer2
// promise1, Promise{<fulfilled>: 'success'}
// promise2,Promise{<rejected>: Error: error!!!}
题17
考点:
Promise的状态一经改变就不能再改变
const promise = new Promise((resolve, reject) => {
resolve("success1");
reject("error");
resolve("success2");
});
promise
.then(res => {
console.log("then: ", res);
}).catch(err => {
console.log("catch: ", err);
})
// then: success1
题18
考点:
catch不管被连接到哪里,都能捕获上层未捕捉过的错误。catch()也会返回一个Promise,且由于这个Promise没有返回值,所以打印出来的是undefined。
const promise = new Promise((resolve, reject) => {
reject("error");
resolve("success2");
});
promise
.then(res => {
console.log("then1: ", res);
}).then(res => {
console.log("then2: ", res);
}).catch(err => {
console.log("catch: ", err);
}).then(res => {
console.log("then3: ", res);
})
// catch:error
// then3:undefined
题19
Promise.resolve(1)
.then(res => {
console.log(res);
return 2; // 会被包装为 resolve(2)
})
.catch(err => {
return 3;
})
.then(res => {
console.log(res);
});
// 1
// 2
题20
Promise.reject(1)
.then(res => {
console.log(res);
return 2;
})
.catch(err => {
console.log(err);
return 3
})
.then(res => {
console.log(res);
});
// 1
// 3
题21
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('timer')
resolve('success')
}, 1000)
})
const start = Date.now();
promise.then(res => {
console.log(res, Date.now() - start)
})
promise.then(res => {
console.log(res, Date.now() - start)
})
// timer
// 1001
// 1002
题22
考点:返回任意一个非
promise的值都会被包裹成promise对象。因此这里的
return new Error('error!!!')也被包裹成了return Promise.resolve(new Error('error!!!'))
Promise.resolve().then(() => {
return new Error('error!!!') // 重点是return
}).then(res => {
console.log("then: ", res)
}).catch(err => {
console.log("catch: ", err)
})
// then: Error:error!!!
// 正常可按照如下2种写法。
return Promise.reject(new Error('error!!!'));
// or
throw new Error('error!!!')
题23
考点:
.then或.catch返回的值不能是 promise 本身,否则会造成死循环。
const promise = Promise.resolve().then(() => {
return promise;
})
promise.catch(console.err)
// Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>
题24
考点:
.then或者.catch的参数期望是函数,传入非函数则会发生值透传
Promise.resolve(1)
.then(2) // 数字类型
.then(Promise.resolve(3)) // 对象
.then(console.log)
// 1
题25
考点:链式调用后面的内容需要等前一个调用执行完才会执行。
就像是这里的finally()会等promise1().then()执行完才会将finally()加入微任务队列,其实如果这道题中你把finally()换成是then()也是这样的
function promise1 () {
let p = new Promise((resolve) => {
console.log('promise1');
resolve('1')
})
return p;
}
function promise2 () {
return new Promise((resolve, reject) => {
reject('error')
})
}
promise1()
.then(res => console.log(res))
.catch(err => console.log(err))
.finally(() => console.log('finally1'))
promise2()
.then(res => console.log(res))
.catch(err => console.log(err))
.finally(() => console.log('finally2'))
// promise1
// 1
// error
// finally1
// finally2