Promise 是异步编程的一种解决方案
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
特点:
对象的状态不受外界影响
一旦状态改变,就不会再变,任何时候都可以得到这个结果。
缺点
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value); //从pending变为resolved;异步操作成功时调用,将异步操作的结果,作为参数传递出去
} else {
reject(error);//从pending变为rejected;异步操作失败时调用,将异步操作报的错误,作为参数传递出去
}
});
//Promise实例生成以后,用then方法分别指定resolved状态和rejected状态的回调函数。
//then接受两个回调函数作为参数,resolve时和reject时,这两个参数是可选的
promise.then(function(value) {
// success
}, function(error) {
// failure
});
Promise 新建后就会立即执行。
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
console.log('Promise2') // 调用resolve或reject并不会终结 Promise 的参数函数的执行
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise
// Promise2
// Hi!
// resolved
一个Promise实例决定另一个Promise实例的情况
const p1 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('fail')), 3000)
})
const p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000)
})
//resolve返回的是p1。由于p2返回的是另一个 Promise,导致p2自己的状态无效了,由p1的状态决定p2的状态。
p2.then(result => console.log(result))
.catch(error => console.log(error))
// Error: fail
//getJSON是一个Promise实例
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);
}).then(function (comments) {
//then返回的是一个新的Promise实例。因此可以采用链式写法,即then方法后面再调用另一个then方法
console.log("resolved: ", comments);
}, function (err){
console.log("rejected: ", err);
});
Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数
promise.then(function(data) { //cb
// success
}).catch(function(err) {
// error
//也可以捕获前面then方法执行中的错误
});
例:
const someAsyncThing = function() {
return new Promise(function(resolve, reject) {
// 下面一行会报错,因为x没有声明
resolve(x + 2);
});
};
someAsyncThing()
.catch(function(error) {
//若someAsyncThing后不是catch,则会报错,Uncaught (in promise) ReferenceError: x is not defined
//promise中的错误会被catch捕获,会接着运行后面那个then()方法指定的回调函数。
//如果没有报错,则会跳过catch()方法
console.log('oh no', error);
})
.then(function() {
console.log('carry on');
});
// oh no [ReferenceError: x is not defined]
// carry on
finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
用于将多个 Promise 实例,包装成一个新的 Promise 实例
Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口;
且返回的每个成员都是 Promise 实例,若不是,会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理
const p = Promise.all([p1, p2, p3]);
p的状态由p1、p2、p3决定,分成两种情况:
如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法
p2没有自己的catch方法,就会调用Promise.all()的catch方法。
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]
Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
const p = Promise.race([p1, p2, p3]);
Promise.allSettled()方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。
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或字符串rejected
// [
// { status: 'fulfilled', value: 42 },
// { status: 'rejected', reason: -1 }
// ]
只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。
将现有对象转为 Promise 对象
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s)
});
// 出错了
出自:阮一峰–ECMAScript 6 入门