Promise 详细说明
上一节:认识 Promise
1. 常用的几种方法
1.1 resolve 方法
resolve 方法作用:将一个普通的值转换成 Promise 类型的数据
方法的状态与结果受参数影响:
- 参数非 Promise 对象,将返回一个 Promise 对象,状态为 fulfilled,结果为参数值
- 参数为 Promise 对象,将返回的 Promise 对象的状态和参数,与参数相同
let p1 = Promise.resolve(123);
console.log(p1); // Promise {<fulfilled>: 123}let p2 = Promise.resolve(new Promise((resolve, reject) => { resolve(456); }));
console.log(p2); // Promise {<fulfilled>: 456}let p3 = Promise.resolve(new Promise((resolve, reject) => { reject("error"); }));
console.log(p3); // Promise {<rejected>: "error"}
1.2 reject 方法
Promise.reject()
方法始终返回一个失败的 Promise 对象,并且不受参数的影响。
let p1 = Promise.reject(123);
console.log(p1); // Promise { <state>: "rejected", <value>: 123 }let p2 = Promise.reject(new Promise((resolve, reject) => { resolve(456); })
);
console.log(p2); // Promise { <state>: "rejected", <value>: 456 }
1.3 catch 方法
Promise.catch()
方法用于捕获 Promise 对象失败的错误。
该方法返回一个新的 Promise 对象,该对象在原 Promise 对象的错误状态被捕获或被处理后,才会发生。
new Promise((resolve, reject) => {reject("error");
}).catch((err) => {console.log(err);
});
1.4 all 方法
Promise 下的 all 方法作用主要针对于多个 Promise 的异步任务的处理,需要接收一个数组类型的参数。
返回值是一个 Promise 对象,状态是由数组中的每一个 Promise 对象的状态来决定的:
- 当所有的 Promise 对象状态均为成功的,最终的结果就是成功的 Promise 对象,结果值是由每一个 Promise 的结果值组成的数组;
- 但凡有一个 Promise 对象的状态为失败,最终的结果就是失败的 Promise 对象,结果值就是失败的这个 Promise 的结果值。
let p1 = new Promise((resolve, reject) => resolve("ok"); );
let p2 = new Promise((resolve, reject) => resolve("hello"); );
let p3 = new Promise((resolve, reject) => reject("error"); );let result = Promise.all([p1, p2, p3]);
console.log(result);
1.5 allSettled 方法
Promise.allSettled()
方法用来确定一组异步操作是否全部结束了
其中包含了 fultilled
和 rejected
两种状态
// 封装一个 ajax 函数
function ajax(url) {return new Promise((resolve, reject) => {let xhr = new XMLHttpRequest();xhr.open("GET", url);xhr.send();xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) resolve(xhr.responseText);else reject(xhr.responseText);}};});
}Promise.allSettled([ajax("http://iwenwiki.com/api/blueberrypai/getChengpinInfo.php"),ajax("http://iwenwiki.com/api/blueberrypai/getListeningInfo.php"),
]).then((value) => {// console.log(value);// 过滤成功和失败两种情况let successList = value.filter((item) => item.status === "fulfilled");console.log(successList);let errorList = value.filter((item) => item.status === "rejected");console.log(errorList);
}).catch((error) => {console.log(error);
});
1.6 any 方法
Promise.any()
方法,参数为一个 Promise 数组
- 参数中只要有一个 Promise 对象状态为 fulfilled,则返回结果为成功
- 只有当全部 Promise 对象的状态均为 rejected,则返回结果为失败。
Promise.any()
跟Promise.race()
方法很像,但是有一点不同,就是Promise.any()
不会因为某个 Promise 对象变成 rejected 状态而结束,必须等到所有参数 Promise 对象变成 rejected 状态才会结束。
let p1 = new Promise((resolve, reject) => { resolve("ok"); });
let p2 = new Promise((resolve, reject) => { resolve("okk"); });
let p3 = new Promise((resolve, reject) => { reject("error"); });let result = Promise.any([p1, p2, p3]);
console.log(result);
1.7 race 方法
Promise.race()
方法需要传递一个参数,参数为数组,数组中的内容表示的是 Promise 实例化对象,如果有最先到达的状态,无论是成功还是失败,都将以这个对象的状态和结果为最终结果。
let p1 = new Promise((resolve, reject) => { resolve("ok"); });
let p2 = new Promise((resolve, reject) => { resolve("okk"); });
let p3 = new Promise((resolve, reject) => { reject("error"); });let result = Promise.race([p2, p1, p3]);
console.log(result); // Promise { <state>: "fulfilled", <value>: okk }
1.8 finally 方法
Promise.finally()
方法是 ES6 中新增的特性,表示无论 Promise 对象变成了 fulfilled 状态或是 rejeced 状态,都会执行指定的回调函数,是不接受参数的。
new Promise((resolve, reject) => {// resolve("ok");reject("error");
}).then((value) => {console.log(value);
}).catch((error) => {console.log(error);
}).finally(() => {console.log("执行了");
});
2. 终止 Promise 链条
终止 Promise 链条原理:通过返回一个空的 Promise 对象来终止 Promise 链条,因为空的 Promise 对象状态为 pending,所以不会触发 then()
、catch()
方法中的回调函数,从而避免了 Promise 链条中后续的回调函数执行。
new Promise((resolve, reject) => {resolve(1);
}).then((value) => {console.log(value); // 1
}).then((value) => {// console.log(value); // undefinedconsole.log(2222);
}).then((value) => {// console.log(value); // undefinedconsole.log(3333);return new Promise(() => {}); // 通过返回一个空的 Promise 对象来终止 Promise 链条
}).then((value) => {// console.log(value); // undefinedconsole.log(4444);
}).then((value) => {// console.log(value); // undefinedconsole.log(5555);
}).catch((error) => {console.log(error);
});
3. 几个关键问题
3.1 如何修改 Promise 对象的状态
Promise 对象的状态有三种:pending、fulfilled、rejected。
let p1 = new Promise((resolve, reject)=>{// 成功// resolve('success');// 失败// reject('error');// 抛出异常// throw '出错了';// 状态只能修改一次resolve('ok')reject('error');
});
console.log(p1);
3.2 指定多个回调函数的执行情况
问题:一个 Promise 实例对象指定多个成功 / 失败的回调函数,都会进行执行吗?
答案:一定都会执行,但是前提是 Promise 对象的状态已经被更改为成功 / 失败,一定不能是 pending 状态。
let p1 = new Promise((resolve, reject) => {// resolve("ok");// reject("error");throw "异常";
});p1.then((value) => { console.log(value); }, (reason) => { console.log(reason); });p1.then((value) => { console.log(value); }, (reason) => { console.log(reason); });// ...
3.3 指定回调与改变状态的先后顺序
改变 Promise 状态和指定回调函数的执行,谁先谁后?
都有可能:
- 若执行器函数中为同步任务,则先修改状态,后指定回调;
- 若执行器函数中为异步任务,则先指定回调,后修改状态。
let p1 = new Promise((resolve, reject) => {// 同步任务// resolve("ok");// 异步任务setTimeout(() => { resolve("ok"); }, 1000);
});p1.then((value) => { console.log(value); },(reason) => { console.log(reason); }
);
3.4 then 方法返回结果
查看上一节 then 方法返回结果
3.5 串联多个任务
Promise.then()
方法的链式操作来举例
new Promise((resolve, reject) => {// reject();resolve('ok')
}).then((value) => {console.log(value);console.log(222);
}).then((value) => {console.log(value);
}).then((value) => { console.log(value); },(reason) => { console.log(reason); }
);
下一节:Promise 进阶