一、串联Promise
我们可以将promise串联起来实现更复杂的异步特性的方法。
每次调用then()或者catch()时都会创建并返回另一个promise,只有当第一个promise完成或被拒绝后,第二个才会被解决。下面是一个例子:
let p1 = new Promise(function(resolve,reject){
resolve(42);
})
p1.then(function(value){
console.log(value);
}).then(function(){
console.log("Finished");
});
实现的结果为:
调用p1.then()之后返回第二个promise,紧接着调用它的then()方法,只有当第一个被解决之后才会调用第二个
1、捕获错误
我们可能在完成处理程序或者拒绝处理程序中发生错误,promise链可以用来捕获这些错误,例如:
let p1 = new Promise(function(resolve,reject){
resolve(42);
})
p1.then(function(value){
throw new Error("Boom");
}).catch(function(error){
console.log(error.message);
});
输出结果为:
p1的完成处理程序抛出了一个错误,链式调用第二个promise的catch()方法之后,可以通过它的拒绝处理程序来接收这个错误,如果拒绝处理程序抛出错误,我们以相同的方式接收错误。例如:
let p1 = new Promise(function(resolve,reject){
throw new Error("Explosoin!")
})
p1.catch(function(error){
console.log(error.message);
throw new Error("Boom");
}).catch(function(error){
console.log(error.message);
});
结果如下:
此处的执行器抛出错误并触发promise p1的拒绝处理程序,这个处理程序又抛出一个错误,并且被第二个promise的拒绝处理程序捕获.。
2、promise链的返回值
promise链的另一个重要的特性是可以给下游promise传递数据,下面是两个例子,无论是完成处理程序还是拒绝处理程序都可以实现:
let p1 = new Promise(function(resolve,reject){
resolve(42);
});
p1.then(function(value){
console.log(value); //42
return value+1;
}).then(function(value){
console.log(value); //43
});
拒绝处理程序的例子:
let p1 = new Promise(function(resolve,reject){
reject(42);
});
p1.catch(function(value){
console.log(value); //42
return value+1;
}).then(function(value){
console.log(value); //43
});
3、在promise链中返回promise
在promise间可以通过完成和拒绝处理程序中返回的原始值来传递数据,如果返回的是对象,则会额外增加一个步骤,请看这个实例:
let p1 = new Promise(function(resolve,reject){
resolve(42);
});
let p1 = new Promise(function(resolve,reject){
resolve(43);
});
//第一个处理完成程序
p1.then(function(value){
console.log(value); //42
return p2;
}).then(function(value){
//第二个处理完成程序
console.log(value); //43
});
与下面是等价的:::
let p1 = new Promise(function(resolve,reject){
resolve(42);
});
let p2 = new Promise(function(resolve,reject){
resolve(43);
});
//第一个处理完成程序
let p3 = p1.then(function(value){
console.log(value); //42
return p2;
});
p3.then(function(value){
//第二个处理完成程序
console.log(value); //43
});
此处第二个完成处理程序被添加到p3并不是p2,如果p2被拒绝的话,那么第二个处理程序就永远不会被调用,例如:
let p1 = new Promise(function(resolve,reject){
resolve(42);
});
let p2 = new Promise(function(resolve,reject){
reject(43);
});
//第一个处理完成程序
p1.then(function(value){
console.log(value); //42
return p2;
}).then(function(value){
//第二个处理完成程序
console.log(value); //从未调用
});
但是我们还是可以通过添加拒绝处理程序来实现:
let p1 = new Promise(function(resolve,reject){
resolve(42);
});
let p2 = new Promise(function(resolve,reject){
reject(43);
});
//第一个处理完成程序
p1.then(function(value){
console.log(value); //42
return p2;
})catch(function(value){
//第二个处理完成程序
console.log(value); //43
});
p2被拒绝后,拒绝处理程序被调用并且传入p2的拒绝值43.
在完成或拒绝处理程序中返回thenable对象不会改变promise执行器的执行器执行时机,先定义的promise的执行器先执行,后定义的后执行,以此类推。
二、自promise继承
promise与其他内建类型一样,也可以作为基类派生其他类,所以你可以定义自己的promise变量来拓展内建promise模型。下面是一个例子:
class mypromise extends Promise{
//使用默认的构造函数
success(resolve,reject){
return this.then(resolve,reject);
}
failure(reject){
return this.catch(reject);
}
}
let promise = new mypromise(function(resolve,reject){
resolve(42);
});
promise.success(function(value){
console.log(value); //42
}).failure(function(value){
console.log(value);
});
因为静态的方法会被继承,所以派生的mypromise也拥有mypromise.then()、mypromise.catch()、mypromise.all()、mypromise.race()方法,后两种与内建一致,前两者稍有不同,如果想要了解更多,可以查阅资料。
三、小结
Promise I的设计目标是改进 Javascrip中的异步编程,它能够让你更好地掌控并组合多个同步操作,比事件系统和回调更实用。 Promise s编排的任务会被添加到 Javascript引擎任务队列并在未来执行,还有一个任务队列用于跟踪Promise的完成处理程序和拒绝处理程序并确保正确执行。
Promise有3个状态:进行中( pending)、已完成( fulfilled)和已Promise I的起始状态是进行中,执行成功会变为已完成,失败则变为已拒绝,在后两种情况下你都可以添加处理程序,以便当 Promise被解决( settled)时做出相应操作,通过 theno方法可以添加完成处理程序或拒绝处理程序,通过catch方法只能添加拒绝处理程序有多种方法可将 Promise链接在一起并在它们之间传递信息,每次调用then()方法会创建并返回一个新的 Promise,它会随前面 Promise被解决而解决这样的链条可用于触发一系列同步事件的响应,也可通过 Promise. race0)方法和 Promise,a()方法来监控多个 Promise的进程并做出相应响应。
参考文档:深入理解ES6