-
Promise
是一个异步的解决方案。
有三种状态:pending、resolved、rejected
一旦状态改变则不会再变化成其他状态。
let p1 = new Promise(function() {
// ...
});
let p2 = new Promise(function() {
// ...
resolve(p1);
})
resolve
可以返回另一个promise
实例,p2
会等待p1
的状态改变,一旦p1
的状态改变成了Resolved
或者Rejected
,那么p2
的回调函数将会立即执行
- 调用
resolve
或reject
并不会终结Promise
的参数函数的执行
new Promise((resolve,reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(1)
})
// 2
// 1
resolve,reject
是在本轮事件循环的末尾执行,并且晚于本轮循环的同步任务,setTimeout
等定时器则在下一轮事件循环执行。
new Promise((resolve, reject) => {
return resolve(1);
//后面的语句不会执行
console.log(2)
})
//1
-
reject
方法的作用等同于抛出错误,如果Promise
状态已经变成resolved
或者rejected
,就会永久保持此状态,不会改变,再抛出错误是无效的。
new Promise((resolve,reject) => {
resolve('success')
throw new Error('error') // 等价于reject('error')
})
// success
Promise
的错误抛出如果没有去catch
则不会冒泡到浏览器,但是如果在Promise
外抛出错误则会冒泡到最外层。
尽量不要用then
中的第二个参数回调来捕获错误,而应该使用catch
当一个Promise
被拒绝时若缺少拒绝处理函数就会默认失败
就是无论Promise
有没有被执行成功,then()\catch()
都可以被正常调用,也不会报错,所以很难通过then()\catch()
来完全判断成功与否,then
里面的reslove()\reject()
回调不写也不会报错
new Promise((resolve,reject) => {
resolve('ok'); //定时器等异步都是在下一次事件循环再执行。而本次循环执行完,Promise也运行结束了!所以错误会在Promise函数体外抛出
setTimeout(() => {
throw new Error('test')
}, 0);
}).then(r => {
console.log(r)
})
// ok
// Uncaught Error: test
-
Promise
链可以捕获前一个promise
的完成或拒绝处理函数中发生的错误 -
Promise
能从一个Promise
传递数据给下一个Promise
的能力
let p1 = new Promise(function(resolve, reject){
resolve(42);
});
p1.then(function(value){
console.log(value); // 42
return value+1;
}).then(function(value){
console.log(value); // 43
});
- 相等前一个
Promise
被解决后才触发另一个Promise
可以在一个promise
里返回另一个promise
,也可以使用async await
-
then
可以串联着写多个,执行多个异步任务,解决Promise
嵌套
p1.then(res => {
p2.then(res => {
p3.then(res => {
})
})
})
可以改写成:
p1.then(res => p2).then(res => p3).then(res => {console.log(res)})
8.Promise.all()
全成功则成功,有一个失败则失败
参数:可迭代对象
返回:是一个Promise
无论p1和p2哪个先完成执行,返回的结果和定义时的结果一致,和完成先后无关
let p1 = new Promise(resolve => resolve(1))
let p2 = new Promise(resolve => resolve(2))
let p3 = new Promise(resolve => resolve(3))
let p = Promise.all([p1, p2, p3])
p.then(res => {
console.log(res)
})
// [1, 2, 3]
如果一个Promise
有自己的catch
方法,则他执行完之后状态会变成resolved
而不是rejected
,因为then
和catch
返回都是一个新的Promise
实例。执行完状态为resolved
。
let p1 = new Promise((resolve, reject) => reject(3)) // rejected
let p2 = new Promise((resolve, reject) => reject(3)).catch(err => {console.log(err)}) // resolved
所以如果此时调用
let p = Promise.all([p1, p2])
p.then(res => {console.log(res)}).catch(err => {console.log(err)})
只会走到then
中,不会进入catch
-
promise.race()
第一个改变的状态就是返回的状态
以下fetch()
异步函数如果在五秒没有执行完,则就抛出错误
const p = Promise.race([
fetch(),
new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('err')), 5000)
})
])
p.then(res => {console.log(res)}).catch(err => {console.log(err)});
-
Promise.resolve()/Promise.reject()
将现有对象转换成Promise
对象,状态为resolved/rejected
11.done()
可以抛出全局错误。
原理:
this.then(onFulfilled, onRejected).catch(err => {
// 下一次事件循环再执行
setTimeout(() => {}, 0);
})
}
finally()
不管最后状态如何都会执行finally
里的回调函数。
原理:
Promise.prototype.finally = function(callback) {
let P = this.constructor; // Promise
return this.then(
// 将callback函数转换成Promise实例
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => {throw reason})
);
}
-
Promise
的继承
可以从Promise
上派生类,自定义自己的一些事件方法, 主要记录一下如何派生类(构造器是什么todo
)(Promise
内部实现 todo)
// 从Promise派生一个myPromise
class myPromise extends Promise{
success(resolve, reject){
return this.then(resolve, reject);
}
}
let promise = new myPromise((resolve, reject)=>{
resolve(42);
});
promise.success(function(value){
console.log(value); // 42
});
var fs = require('fs');
function readFile(fileName){
return new Promise((resolve, reject)=>{
console.log('promise come in');
// 异步操作
fs.readFile(fileName, 'utf-8', function(err, data){
console.log('promise come in readFile');
if(err){
console.log('promise come in readFile err');
reject(err);
}
else{
console.log('promise come in readFile success');
resolve(data);
}
});
});
}
let promise = readFile('demo.txt');
promise.then(
function(data){
console.log("resolve", data);
},
function(err){
console.log("reject", err);
}
).then(function(){
console.log('after then');
throw new Error('error messsage');
})
.catch((err)=>{
console.log('catch err');
console.log(err.message);
});
console.log('all come in');