Promise 规范与原理解析 | 京东物流技术团队
摘要
Promise 对象用于清晰的处理异步任务的完成,返回最终的结果值,本次分享主要介绍 Promise 的基本属性以及 Promise 内部的基础实现,能够帮我们更明确使用场景、更快速定位问题。
Promise 出现的原因
首先我们先来看一段代码:异步请求的层层嵌套
或者我们可以将上面的代码优化为下面这样
由上面的两种写法的请求可见,在 promise 之前,为了进行多个异步请求并且依赖上一个异步请求的结果时,我们必须进行层层嵌套,大多数情况下,我们又对异步结果进行数据处理,这样使得我们的代码非常难看,并且难以维护,这就形成了回调地狱,由此 Promise 开始出现了。
回调地狱缺点
代码臃肿
可读性差
耦合性高
不好进行异常处理
Promise 的基本概念
含义
ES6 将其写进了语言标准里统一了用法,是一个构造函数,用来生成 Promise 实例
参数为一个执行器函数(执行器函数是立即执行的),该函数有两个函数作为参数,第一个参数是成功时的回调,第二个参数是失败时的回调
函数的方法有 resolve(可以处理成功和失败)、reject(只处理失败)、all 等方法
then、catch、finally 方法为 Promise 实例上的方法
状态
pending --- 等待状态
Fulfilled --- 执行状态 (resolve 回调函数,then)
Rejected --- 拒绝状态 (reject 回调函数,catch)
状态一旦改变就不会再变,状态只可能是两种改变,从 pending->Fulfilled,pending->Rejected
有两个关键的属性:PromiseState --- 状态改变,PromiseResult --- 结果数据改变
特点
错误信息清晰定位:可以在外层捕获异常信息(网络错误、语法错误都可以捕获),有“冒泡”性质,会一直向后传递,直到被捕获,所以在最后写一个 catch 就可以了
链式调用:每一个 then 和 catch 都会返回一个新的 Promise,把结果传递到下一个 then/catch 中,因此可以进行链式调用 --- 代码简洁清晰
结果由什么决定
resolve
如果传递的参数是非 Promise 类型的对象,则返回的结果是成功状态的 Promise 对象,进入下一个 then 里面
如果传递的参数是 Promise 类型的对象,则返回的结果由返回的 Promise 决定,如果返回的是 resolve 则是成功的状态,进入下一个 then 里,如果返回的是 reject 则是失败的状态,进入下一个 catch 里
reject
如果传递的参数是非 Promise 类型的对象,则返回的结果是拒绝状态的 Promise 对象,进入下一个 catch 里面或者是下一个 then 的第二个参数 reject 回调里面
如果传递的参数是 Promise 类型的对象,则返回的结果由返回的 Promise 决定,如果返回的是 resolve 则是成功的状态,进入下一个 then 里,如果返回的是 reject 则是拒绝的状态,进入下一个 catch 里面或者是下一个 then 的第二个参数 reject 回调里面
这在我们自己封装的 API 里面也有体现:为什么 code 为 1 时都是 then 接收,其他都是 catch 接收,就是因为在 then 里面也就是 resolve 函数中对 code 码进行了判断,如果是 1 则返回 Promise.resolve(),进入 then 里处理,如果是非 1 则返回 Promise.reject(),进入 catch 里处理。
流程图
简单使用
手写实现简单的 Promise
通过上面的回顾,我们已经了解了 Promise 的关键属性和特点,下面我们一起来实现一个简单的 Promise 吧
针对 resolve 中返回 Promise 对象时的内部执行顺序
总结
以上就是我们常用的 Promise 基础实现,在实现过程中对比了 Promise 和函数嵌套处理异步请求的优缺点,Promise 仍存在缺点,但是的确方便很多,同时更清晰的理解到错误处理如何进行异常穿透的,也能帮助我们更规范的使用 Promise 以及快速定位问题所在。
作者:京东物流 孙琦
来源:京东云开发者社区 自猿其说 Tech 转载请注明来源
版权声明: 本文为 InfoQ 作者【京东科技开发者】的原创文章。
原文链接:【http://xie.infoq.cn/article/558342573da838270da0d5ac4】。文章转载请联系作者。
评论