前言
一个 Promise 对象可以理解为一次将要执行的操作(常常被用于异步操作),使用了 Promise 对象之后可以用一种链式调用的方式来组织代码,让代码更加直观。而且由于 Promise.all 这样的方法存在,可以让同时执行多个操作变得简单。
Promise的兴起,是因为异步方法调用中,往往会出现回调函数一环扣一环的情况。这种情况导致了回调金字塔问题的出现。不仅代码写起来费劲又不美观,而且问题复杂的时候,阅读代码的人也难以理解。
举例如下:
db.save(data, function(data){ // do something... db.save(data1, function(data){ // do something... db.save(data2, function(data){ // do something... done(data3); // 返回数据 }) });});
假设有一个数据库保存操作,一次请求需要在三个表中保存三次数据。那么我们的代码就跟上面的代码相似了。这时候假设在第二个db.save
出了问题怎么办?基于这个考虑,我们又需要在每一层回调中使用类似try...catch
这样的逻辑。这个就是万恶的来源,也是node刚开始广为诟病的一点。
另外一个缺点就是,假设我们的三次保存之间并没有前后依赖关系,我们仍然需要等待前面的函数执行完毕, 才能执行下一步,而无法三个保存并行,之后返回一个三个保存过后需要的结果。(或者说实现起来需要技巧)
不幸的是,在我刚开始接触node的时候,我写了大量这样的hell。
后来因为还是写前端代码多一些,我接触了ES6,发现了一个解决回调深渊的利器Promise。
其实早在ES6的Promise之前,Q,when.js,bluebird等等库早就根据Promise标准(参考Promise/A+)造出了自己的promise轮子。
(看过一篇文章,我觉得很有道理。里面说,不要扩展内置的原生对象。这种做法是不能面向未来的。所以这里有一个提示:使用扩展原生Promise的库时,需要谨慎。)
这里仅讨论原生的Promise。
ES6 Promise
Promise对象状态
在详解Promise之前,先来点理论:
Promise/A+规范, 规定Promise对象是一个有限状态机。
它三个状态:
1、pending
(执行中)
2、fulfilled
(成功)
3、reject
(拒绝)
其中pending
为初始状态,fulfilled
和rejected
为结束状态(结束状态表示promise的生命周期已结束)。
状态转换关系为:
pending->fulfilled,pending->rejected。
随着状态的转换将触发各种事件(如执行成功事件、执行失败事件等)。
Promise形式
Promise的长相就像这样子:
新闻热点
疑难解答
图片精选