问题/需求:
- 手写
Promise A+
规范. 啥是A+其实我也不是很懂, 好像就是平时用的那一种? 不管了, 先上了再说.
解决/处理步骤:
分析过程:
Promise
, 先得想清楚, 这玩意儿能干啥, 可以干啥, 才能反向推出, 我们该咋写.
Promise
有可以传递参数, 参数一个, 而且是个函数, 准确的说是两个函数, 而且是钩子函数(hook
就是resolve
和 reject
, 我们平时在使用的时候, 如果内部处理完成符合我们的预期就resolve
, 不符合或者报错就使用reject
.
promise
好像还有Promise.resolve()
, Promise.reject()
, Promise.all()
, Promise.race()
这些静态方法. 不管, 先一步一步来.
- 先最简单, 也是最基础的, 就是
Promise
其实管理着三种方法, 在没有resolve
和reject
之前, 是pending
状态, 也就是等待状态, 在resolve
之后, pending=> fulfilled
, 或者在reject
之后, pending => rejected
状态, 并且, 一旦状态发生改变, 就没办法再次改变了.
初步实现
- 既然理清了
Promise
的基本使用和其有的方法, 那么, 我们就开始从最简单的Promise
开始撸.
- 这里, 将使用
class
来定义, 其实也可以使用函数和Prototype原型
来实现.
class Promise{
constructor(exector){
exector(this.resolve, this.reject)
}
resolve(){}
reject(){}
}
加入状态管理
- 但是你会发现, 如果你在Promise中调用了resolve和reject方法, 她会都进行调用, 这和我们平时用到的Promise一旦resolve,或者reject后, 就无法改变状态不一致, 对了! 这里就得加入状态管理.
class Promise{
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor(exector){
this.staus = Promise.PENDING
this.value = null
exector(this.resolve, this.reject)
}
resolve(value){
if(this.status=== Promise.PENDING){
this.value = value
this.status = Promise.FULFILLED
}
}
reject(reason){
if(this.status=== Promise.PENDING){
this.value = reason
this.status = Promise.REJECTED
}
}
}
- 好, 到这一步, 既实现了功能, 又有状态管理, 不会被多次执行了. 但是, 其中还有问题, 如果, 用户在
resolve
或者reject
中出现了异常咋办呢? 简单, 加上try{}catch{}
不就好了! 好, 那咱们来加上!
class Promise{
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor(exector){
this.staus = Promise.PENDING
this.value = null
+ try{
+
+ exector(this.resolve, this.reject)
+ }catch (error){
+ this.reject(error)
+ }
+ }
resolve(value){
if(this.status=== Promise.PENDING){
this.value = value
this.status = Promise.FULFILLED
}
}
reject(reason){
if(this.status=== Promise.PENDING){
this.value = reason
this.status = Promise.REJECTED
}
}
}
- 在
constructor
中的exector
外面包一层trycatch
, 这样出现了异常会reject
出来.
- 好了, 到目前为止, 确实是实现了
resolve
、reject
并且, 状态改变后, 不会再进行二次改变了. 现在来问一个问题, 使用Promise
是用来解决什么, 或者Promise
是为啥出现的, 你一定知道答案!
对! 答案就是为了解决回调地狱
问题, 所以, Promise是可以链式执行的.使用的就是then()
方法, 所以, 下面我们就来实现then()
方法
then链式执行
- then方法一样, 里面两个钩子方法, 一个是
onfulfilled
和onrejected
, 分别和上面的resolve
、reject
对应, 如果上面是使用了resolve
, 那么then
中的onfulfilled
方法就会被执行, 返回resolve
中的data
, 如果上面使用了reject
, then
中的onrejected
方法就会被执行.
- 下面就来实现一下then方法, 这里就只写then部分的代码了, 防止代码太多, 没有重点.
then(onfulfilled, onrejected){
if(typeof onfulfilled !== 'function'){ onfulfilled = () => {}}
if(typeof onrejected !== 'function'){ onrejected = () => {}}
return new Promise((resolve, reject)=>{
if(this.status === Promise.FULFILLED){
setTimeout(()=>{
try{
onfulfilled(this.value)
}catch(err){
onrejected(err)
}
},0)
}
if(this.status ==== promise.REJECTED){
setTimeout(()=>{
try{
onrejected(this.value)
}catch(err){
onrejected(err)
}
})
}
if(this.status === promise.PENDING){
this.callbacks.push({
onfulfilled:value=>{
try{
onfulfilled(value)
}catch(error){
onrejected(error)
}
},
onrejected:reason=>{
try{
onrejected(value)
}catch(error){
onrejected(error)
}
}
})
}
})
}
- 写到这一步, 基本就把
then
方法中的几种情况搞定了, 但是! 这里应该有人会看出来, 我们把没有立即执行的方法push
到了回调数组中, 那不能放在那不管了吧! 所以, 这里其实, 在上一步的resolve
和reject
中, 应该做一些操作, 具体操作如下:
resolve(value){
if(this.status === NewP.PENDING){
this.status = NewP.FULFILLED
this.value = value
+ setTimeout(() => {
+ this.callbacks.map(callback => {
+ callback.onfulfilled(this.value)
+ })
+ })
}
}
reject(reason){
if(this.status=== NewP.PENDING){
this.status = NewP.REJECT
this.value = reason
+ setTimeout(() => {
+ this.callbacks.map(callback => {
+ callback.onrejected(this.value)
+ })
+ });
}
}
- 其实就是在当前的方法执行完了以后,去看看回调方法数组中, 有没有没被执行完的, 如果有, 就得去执行, 但是! 这里注意了, 执行回调函数数组中的方法, 应该是异步的, 所以,这里我们给加上了
setTimeout
定时器.
好了, 到目前, 我们已经实现了reslove, reject, then方法. all、race方法, 将下一个文章输出. 前端小白, 有错误和不当之处, 忘各位大神指出, 如果感觉小弟码字不易, 麻烦给个👍, 谢谢!