# Promise 对象
# 1.Promise 的含义
- Promise 是异步编程的一种解决方案,避免层层嵌套的回调函数。
- Promise 是一个对象,用它来获取异步操作的消息。Promise 提供了统一的 API,可以对异步操作的结果做进一步的处理。 Promise对象的两个特点
- 对象的状态不受外界影响。有三种状态,
pending(进行中)、fulfilled(已成功)和rejected(已失败)。 - 一旦状态改变,就不会再变。
Promise对象状态的改变只有两种可能:从pending变成fulfilled和从pending变成rejected。只要这两种情况发生了,那么状态就resolved(已定型),一直保持这个结果。 Promise对象的一些缺点 Promise一旦新建,就无法中途取消。- 如果不设置
Promise的catch方法,Promise内部抛出错误,不会反应到外部。 - 当处于
pending状态时,无法得知进展到哪个阶段。
// 内部报错,外部捕获不到
try {
new Promise((resolve, reject) => {
console.log(w) // 此处报错
resolve(1)
})
} catch(e) {
console.log('error', e)
}
// Uncaught (in promise) ReferenceError: w is not defined
// 使用catch方法就可以捕获
new Promise((resolve, reject) => {
console.log(w) // 此处报错
resolve(1)
}).catch(e => {
console.log('2', e)
})
// 2 ReferenceError: w is not defined
# 2.Promise基本用法
setTimeout(_ => {
console.log(1)
}, 0)
new Promise((resolve, reject) => {
console.log(2) // 此处报错
resolve(3)
console.log(4)
}).then(value => {
console.log(value)
})
console.log(5)
// 2 4 5 3 1
Promise构造函数接受一个函数作为一个参数,该函数有两个参数resolve和reject。resolve函数作用是将Promise对象的状态从pending变为fulfilled。reject函数作用是将Promise对象的状态从pending变为rejected。
return语句才会阻止后面的执行
new Promise((resolve, reject) => {
return resolve(1)
// 后面语句不会执行
console.log(2)
}).then(value => {
console.log(value)
})
// 1
# 3.Promise.prototype.then()
- 第一个参数是
resolved状态的回调函数。 - 第二个参数是
rejected状态的回调函数(可选)。
new Promise((resolve, reject) => {
return resolve(1)
}).then(value => {
console.log(value)
}, reason => {
console.log(reason)
})
// 1
then方法返回的是一个新的Promise实例,因此可以采用链式写法。
new Promise((resolve, reject) => {
return resolve(1)
}).then(value => {
console.log(value)
}).then(v => {
// 前一个then没有返回值 所以 undefined
console.log(v)
return 2
}).then(v => {
// 前一个then返回2 所以输出 2
console.log(v)
let P2 new Promise((r, j) => {
r(3)
})
return P2
}).then(v => {
// 当前then等待的是P2状态的改变的
console.log(v)
})
// 1 undefined 2 3
# 4.Promise.prototype.catch()
- 运行中抛出错误,也会被
catch方法捕获(throw new Error())。
const promise = new Promise(function(resolve, reject) {
throw new Error('test');
});
promise.catch(function(error) {
console.log(error);
});
// Error: test
var promise = new Promise(function(resolve, reject) {
console.log(www)
});
promise.catch(function(error) {
console.log('2', error);
});
// 2 ReferenceError: www is not defined
- 上面的写法等价于
// 写法一
const promise = new Promise(function(resolve, reject) {
try {
throw new Error('test');
} catch(e) {
reject(e)
}
});
// 写法二
const promise = new Promise(function(resolve, reject) {
reject(new Error('test'));
});
# 5.Promise.prototype.finally()
- 不管
Promise对象最后状态如何,都会执行finally()方法()。 finally方法的回调函数不接受任何参数。finally方法的实现方式。
Promise.prototype.finally = function (callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};
# 5.Promise.all()
Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例.
const p = Promise.all([p1, p2, p3]);
p的状态由p1、p2、p3决定,分成两种情况- 只有
p1、p2、p3状态都变成fulfilled,p状态就变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。 - 只要
p1、p2、p3之中有一个状态都变成rejected,则p状态就变成rejected,此时rejected的返回值,传递给p的回调函数。
- 只有
# 6.Promise.race()
Promise.race()方法的参数使用跟Promise.all()方法时一样的。- 只要
p1、p2、p3之中有一个实例率先改变了状态,,则p的状态就跟着变。此时率先改变的实例的返回值,传递给p的回调函数。
const p = Promise.race([
getPost(),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p
.then(console.log)
.catch(console.error);
- 上面代码中,如果
5秒之内getPost方法无法返回结果,变量p的状态就会变为rejected,从而触发catch方法指定的回调函数。
# 7.Promise.allSettled()
Promise.allSettled()方法的参数使用跟Promise.all()方法时一样的。- 只有
p1、p2、p3状态都都发生了改变,此时p1、p2、p3的实例组成一个数组,传递给p的回调函数。
const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);
const allSettledPromise = Promise.allSettled([resolved, rejected]);
allSettledPromise.then(function (results) {
console.log(results);
});
// [
// { status: 'fulfilled', value: 42 },
// { status: 'rejected', reason: -1 }
// ]
# 8.Promise.resolve()
- 将现有的对象转为
Promise对象。 - 参数有一下四种情况
- 参数是一个
Promise实例- 不做修改,直接返回当前这个实例
- 参数是一个
thenable对象(具有then方法的对象)- 会立即执行
then方法
- 会立即执行
- 参数不具有
then方法,或者不是一个对象- 会把这个参数传给回调函数
- 不带参数
- 会把这个参数(undefined)传给回调函数
- 参数是一个
# 8.Promise.resolve()
- 将
Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected. Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数(这是与Promise.resolve的不同之处)。
const thenable = {
then(resolve, reject) {
reject('出错了');
}
};
Promise.reject(thenable)
.catch(e => {
console.log(e === thenable)
})
// true
# 9.Promise.any().(提案)
Promise.any()方法的参数使用跟Promise.all()方法时一样的。- 只有
p1、p2、p3状态都变成rejected - 只要
p1、p2、p3之中有一个状态变成fulfilled,则p的状态就会发生改变。