ES6 规定,Promise
对象是一个构造函数,用来生成Promise
实例。
下面代码创造了一个Promise
实例。
const promise=new Promise(function(resolve,reject){
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
})
Promise
构造函数接受一个函数作为参数,该函数的两个参数分别是resolve
和reject
。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve
函数的作用是,将Promise
对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject
函数的作用是,将Promise
对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise.prototype.then()
Promise 实例具有then
方法,也就是说,then
方法是定义在原型对象Promise.prototype
上的。
作用是为 Promise 实例 添加 状态改变时的回调函数。
第一个参数是resolved
状态的回调函数,第二个参数(可选)是rejected
状态的回调函数。
then
方法返回的是一个新的Promise
实例(注意,不是原来那个Promise
实例)。因此可以采用链式写法,即then
方法后面再调用另一个then
方法。
//Pending(等待、处理中) ---> Resolve(完成,fullFilled) ---> Reject(拒绝,失败)
var p1 = new Promise(function(resolve,reject){
resolve(1); // 成功了
// reject(2); // 失败了
});
// 接收成功和失败的数据,通过then来传递
// then也是返回一个promise对象,会继续往下传递数据,传递给下一个then
p1.then(function(value){
// resolve
console.log(value);
return value + 1; // 1
alert(`成功了:${value}`);
},function(value){
// reject
alert(`失败了:${value}`);
}).then(function(value){
console.log(value); // 2
});
Promise.prototype.catch()
用于指定发生错误时的回调函数。
var p1 = new Promise(function(resolve,reject){
//resolve(1); // 成功了
reject(2); // 失败了
});
p1.then(function(value){
// resolve
console.log(value);
return value + 1;
}).catch(function(value){
console.log(value); //2
return value + 1;
}).then(function(value){
console.log(value); // 3
});
then
方法指定的回调函数,如果运行中抛出错误,也会被catch
方法捕获。
//catch捕获异常错误
var p1 = new Promise(function(resolve,reject){
resolve('成功了');
});
p1.then(function(value){
console.log(value); // 成功了
// throw是用来抛错误的
throw '发生了点小意外';
}).catch(function(e){
// catch用来捕获这个错误的 ---> 追踪
console.log(e); // 发生了点小意外
});
如果 Promise 状态已经变成resolved,再抛出错误是无效的。
const promise = new Promise(function(resolve, reject) {
resolve('ok');
throw new Error('test');
});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });
// ok
一般来说,不要在then
方法里面定义 Reject 状态的回调函数(即then
的第二个参数),总是使用catch
方法。
Promise.all()
Promise.all
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
var p=Promise.all([p1,p2,p3])
//Promise.all([p1,p2,p3,...]); 所有的promise对象,都正确,才走成功
//否则,只要有一个错误,就走失败
var p1 = Promise.resolve(1);
var p2 = Promise.reject(0);
Promise.all([true,p1,p2]).then(function(obj){
console.log(`成功了:${obj}`);
},function(obj){
console.log(`失败了:${obj}`);
});
Promise.race()
var p=Promise.race([p1,p2,p3])
// race ---> 返回的也是一个promise对象
//最先执行的的promise结果,哪个最快我用哪个
var p1 = new Promise(function(resolve,reject){
setTimeout(resolve,50,'one');
});
var p2 = new Promise(function(resolve,reject){
setTimeout(resolve,100,'two');
});
Promise.race([p1,p2]).then(function(val){
console.log(val);
});
Promise.resolve()
有时需要将现有对象转为 Promise 对象,Promise.resolve
方法就起到这个作用。
Promise.resolve
等价于下面的写法。
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
应用
加载图片
将图片的加载写成一个Promise
,一旦加载完成,Promise
的状态就发生变化。
const preloadImage = function (path) {
return new Promise(function (resolve, reject) {
const image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};
//Generator 函数 与 Promise结合