Promise 是一个 ECMAScript 6 提供的类,是异步编程的一种解决方案,目的是更加优雅地书写复杂的异步任务,比传统的解决方案——回调函数和事件——更合理和更强大。
1.基本用法(.then .catch .finally)
Promise 类有 .then() .catch() 和 .finally() 三个方法,这三个方法的参数都是一个函数,.then() 可以将参数中的函数添加到当前 Promise 的正常执行序列,.catch() 则是设定 Promise 的异常处理序列,.finally() 是在 Promise 执行的最后一定会执行的序列。 .then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列。
new Promise(function (resolve, reject) {
var a = 0;
var b = 1;
if (b == 0) reject("Divide zero");
else resolve(a / b);
}).then(function (value) {
console.log("a / b = " + value);
}).catch(function (err) {
console.log(err);
}).finally(function () {
console.log("End");
});
执行结果:
a / b = 0
End
2.Promise.resolve()
将现有对象转为 Promise 对象 ①参数是一个 Promise 实例 如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。 ②参数是一个thenable对象 thenable对象指的是具有then方法的对象
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function (value) {
console.log(value);
});
③参数不是具有then()方法的对象,或根本就不是对象 如果参数是一个原始值,或者是一个不具有then()方法的对象,则Promise.resolve()方法返回一个新的 Promise 对象,状态为resolved。
const p = Promise.resolve('Hello');
p.then(function (s) {
console.log(s)
});
④不带有任何参数 Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。 所以,如果希望得到一个 Promise 对象,比较方便的方法就是直接调用Promise.resolve()方法。
const p = Promise.resolve();
p.then(function () {
});
3.Promise.reject()
Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。
const p = Promise.reject('出错了');
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s)
});
4.Promise.all()
const p = Promise.all([p1, p2, p3]);
Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例. (1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。 (2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
5.Promise.race()
const p = Promise.race([p1, p2, p3]);
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
6.Promise.allSettled()
只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。
const promises = [
fetch('/api-1'),
fetch('/api-2'),
fetch('/api-3'),
];
await Promise.allSettled(promises);
removeLoadingIndicator();
上面示例中,数组promises包含了三个请求,只有等到这三个请求都结束了(不管请求成功还是失败),removeLoadingIndicator()才会执行。
7.Promise.any()
只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。
const promises = [
fetch('/endpoint-a').then(() => 'a'),
fetch('/endpoint-b').then(() => 'b'),
fetch('/endpoint-c').then(() => 'c'),
];
try {
const first = await Promise.any(promises);
console.log(first);
} catch (error) {
console.log(error);
}
上面代码中,Promise.any()方法的参数数组包含三个 Promise 操作。其中只要有一个变成fulfilled,Promise.any()返回的 Promise 对象就变成fulfilled。如果所有三个操作都变成rejected,那么await命令就会抛出错误。
8.Promise.try()
不管函数f是否包含异步操作,都用then方法指定下一步流程,用catch方法处理f抛出的错误。
function getUsername(userId) {
return database.users.get({id: userId})
.then(function(user) {
return user.name;
});
}
Promise.try(() => database.users.get({id: userId}))
.then(...)
.catch(...)
|