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结合