ES6-Promise
我们知道的,在 JavaScript 中,所有代码都是单线程的,也就是同步执行的。而 Promise 就为异步编程提供了一种解决方案。
1 基本概念
-
名称:
译为“承诺”,这也就表达了将来会执行的操作,代表异步操作; -
状态:
一共有三种状态,分别为pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。 -
特点:
(1)只有异步操作可以决定当前处于的状态,并且任何其他操作无法改变这个状态;
(2)一旦状态改变,就不会在变。状态改变的过程只可能是:从pending
变为fulfilled
和从pending
变为rejected
。如果状态发生上述变化后,此时状态就不会在改变了,这时就称为resolved
(已定型)
2 基本用法
Promise 对象是由关键字 new 及其构造函数来创建的。
首先,
介绍一下如何创建一个 Promise;
const promise = new Promise((resolve, reject) => {
// do something here ...
if (success) {
resolve(value); // fulfilled
} else {
reject(error); // rejected
}
});
由上述代码我们可知:
该构造函数接收两个函数作为参数,分别是resolve
和reject
。
当异步操作执行成功后,会将异步操作结果作为参数传入resolve
函数并执行,此时Promise
对象状态从pending
变为fulfilled
;
失败则会将异步操作的错误作为参数传入reject
函数并执行,此时Promise
对象状态从pending
变为rejected
;
接下来,
我们通过then
方法,分别指定resolved状态和rejected状态的回调函数。
promise.then(function(value) {
// success
}, function(error) {
// failure
});
then
方法可以接收两个回调函数作为参数,第一个回调函数就是fulfilled
状态时调用;第二个回调函数就是rejected
时调用。这边的第二个参数是可选的,不一定要提供。
3 方法
(1) Promise.all(iterable)
- 参数
iterable 必须是一个可迭代对象,如 Array 或 String。 - 返回值
一个新的Promise
实例。
Promise.all 的使用
如果传入的参数中存在不是Promise
实例,则会先调用Promise.resolve
,将其转为Promise
实例,再进一步处理。
var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([p1, p2, p3]).then(values => {
console.log(values);
});
// [3, 1337, "foo"]
Promise.all 的异步和同步
如果传入的参数为空的可迭代对象,则同步返回一个已完成(already resolved)状态的 Promise;
非空时则返回一个异步完成(asynchronously resolved) Promise
var iterable = [Promise.resolve(1), Promise.resolve(2)];
var p = Promise.all(iterable);
console.log(p);
setTimeout(function(){
console.log(p);
});
// Promise {<pending>}
// Promise {<resolved>: Array(2)}
Promise.all 的快速返回失败行为
传入的参数中任意一个promise
返回失败时,那么整体立即返回失败,返回的错误信息是第一个失败的promise
结果。
var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
reject('p4 reject!');
});
var p5 = new Promise((resolve, reject) => {
reject('p5 reject!');
});
Promise.all([p1, p2, p3, p4, p5]).then(values => {
console.log(values);
}, reason => {
console.log(reason)
});
// p4 reject!
.
.
.
.
.
.
(2) Promise. race(iterable)
- 参数
iterable 必须是一个可迭代对象,如 Array 或 String。 - 返回值
一个新的Promise
实例。
Promise.race 的使用
race
有赛跑之译,因此返回的新实例状态,是跟随参数中最先改变状态的那个实例;如果不是Promise
实例,依旧先用Promise.resolve
方法,转化后再进一步处理。
如果传的迭代为空,则返回的Promise
永远等待
var promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one-resolve-500');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(reject, 400, 'two-reject-400');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value);
}, function(err) {
console.log(err);
});
// two-reject-400
.
.
.
.
.
.
(3) Promise.resolve(value)
返回一个以给定的值解析后的Promise
对象;
参数 value 主要有以下几种情况:
-
一个
Promise
实例
原封不动的返回该实例;var original = Promise.resolve('我在第二行'); var cast = Promise.resolve(original); cast.then(function(value) { console.log('value: ' + value); }); console.log('original === cast ? ' + (original === cast)); // "original === cast ? true" // "value: 我在第二行"
-
一个
thenable
对象:是指含有then
方法的对象
跟随这个thenable
对象的,采用它的最终状态;let thenable = { then: function(resolve, reject) { resolve(42); } } let p = Promise.resolve(thenable); p.then(function(value) { console.log(value); }) // 42
-
普通数据:[String|Array|Object|Number]
直接将传入参数当最终结果并返回一个新的Promise
;let p = Promsie.resolve(123); p.then(function(num) { console.log(num); }) // 123
-
无参数
直接返回一个resolved
状态的Promise
对象let p = Promsie.resovle(); p.then(function() { // do something here... })
.
.
.
.
.
.
(4) Promise.reject(reason)
- 参数:表示被拒绝的原因;
⚠️传入的参数会原封不动的作为 reject 函数的理由,并不会因为传入的参数 Promise 或者是 thenable 对象而有所不同
- 返回值:一个含有
reason
的状态为rejected
的Promise
.
.
.
.
.
.
4 Promise原型
(1) Promise.prototype.then()
Promise 的实例具有
then
方法,主要作用是为 Promise 实例发生状态改变时添加回调函数。
它接收两个回调函数作为参数,第一个参数是fulfilled
状态时的回调函数;第二个参数是rejected
状态时的回调函数,可不传入。
并且该方法返回一个新的Promise
对象。
- 语法:
p.then(onResolve, onReject); p.then(function(value) { // fulfillment }, function(reason) { // rejection });
.
.
.
.
(2) Promise.prototype. catch()
返回一个
Promise
,并且处理拒绝的情况。它的行为与调用Promise.prototype.then(undefined, onRejected)
相同。
- 语法
p.catch(onReject) p.catch(function(reason) { // 拒绝 });
- 推荐使用
catch
方法,不要在then
方法中定义rejected
状态的回调函数;这是因为使用catch
还可以捕获在then
方法执行中存在的错误。// bad promise .then(function(data) { // success }, function(err) { // error }); // good promise .then(function(data) { // success }) .catch(function(err) { // error });
.
.
.
.
.
.
(3) Promise.prototype. finally()
返回一个
Promsie
。是指,在上一轮 promise 运行结束后,无论fulfilled
还是rejected
,都会执行指定的回调函数。
该方法适合,无论结果如何都要进行的操作,例如清除数据。
- 语法:该回调函数的不接受任何参数;
p.finally(onFinally); p.finally(function() { })