手写promise

作者: 姜治宇 | 来源:发表于2020-04-01 11:25 被阅读0次

promise承诺,是es6一个非常重要的解决回调地狱的工具,其本质就是个观察者模式。其实现思路是:
在then注册事件,通过resolve或reject触发事件。
今天我们就试着手写一个简版的promise,对大家理解promise更有帮助。

第一步:整体框架

我们先搭一个promise的整体框架:

function myPromise(callback){
    function resolve(){
        console.log('ok')
    }
    function reject(){
        console.log('error')
    }
    callback(resolve,reject)


}

let p = new myPromise(function(resolve,reject){
    setTimeout(function(){
        resolve()
    },500)
})

别小看这段代码,这里涉及到高阶函数的概念,请大家仔细咂摸一下。如果实在看不明白也不要紧,那先看个简单的:

let convert = function(val,fn){
    //转换val值,fn是转换规则
    return fn(val)
}

let toInt = function(val){
    return parseInt(val)
}
let res = convert('100.2',toInt)
console.log(res)

高阶函数的高阶,就是往上走,先不执行,其实就是延迟执行

第二步:填充属性

框架有了,下面需要准备一些必备属性了。
观察者模式大家想必都比较熟悉,我们起码需要一个数组,用来存放待触发的函数。
promise需要的属性清单是:
1、两个数组,分别存放成功和失败两种情况下待触发的函数。
2、状态属性,因为promise有三种状态,分别是:pending、resolve和reject。
3、成功和失败的value信息。
好,我们再完善一下代码:

function myPromise(callback){
    var self = this;
    self.status = 'pending'//状态位
    self.onFulfilledCallbacks = []//存放成功触发的函数
    self.onRejectedCallbacks = []//存放失败触发的函数
    self.value = null//成功的返回值
    self.reason = null//失败的返回值
    function resolve(value){
        if(self.status === 'pending'){
            self.status = 'fulfilled'
            self.value = value;
            self.onFulfilledCallbacks.forEach(fn=>fn())

        }
    }
    function reject(reason){
        if(self.status === 'pending'){
            self.status = 'rejected'
            self.reason = reason;
            self.onRejectedCallbacks.forEach(fn=>fn())
        }
    }
    try{
        callback(resolve,reject) //执行高阶函数
    }catch(err){
        reject(err)
    }
}

第三步:then函数

then就是用来注册待触发的函数。

myPromise.prototype.then = function(onFulfilled,onRejected){
    let self = this;
    if(self.status === 'pending'){
        self.onFulfilledCallbacks.push(function(){
            onFulfilled(self.value)
        })
        self.onRejectedCallbacks.push(function(){
            onRejected(self.reason)
        })
    }
}

第四步:测试一下

function myPromise(callback){
    var self = this;
    self.status = 'pending'
    self.onFulfilledCallbacks = []
    self.onRejectedCallbacks = []
    self.value = null
    self.reason = null
    function resolve(value){
        if(self.status === 'pending'){
            self.status = 'fulfilled'
            self.value = value;
            self.onFulfilledCallbacks.forEach(fn=>fn())

        }
    }
    function reject(reason){
        if(self.status === 'pending'){
            self.status = 'rejected'
            self.reason = reason;
            self.onRejectedCallbacks.forEach(fn=>fn())
        }
    }
    try{
        callback(resolve,reject) //执行高阶函数
    }catch(err){
        reject(err)
    }
}

myPromise.prototype.then = function(onFulfilled,onRejected){
    let self = this;
    if(self.status === 'pending'){
        self.onFulfilledCallbacks.push(function(){
            onFulfilled(self.value)
        })
        self.onRejectedCallbacks.push(function(){
            onRejected(self.reason)
        })
    }
}

new myPromise(function(resolve,reject){
    setTimeout(function(){
        resolve({code:200,data:'ok'})
    },500)
}).then(function(res){
    console.log(res)
})

第五步:修正

还有点小瑕疵不知道大家注意到木有:

new myPromise(function(resolve,reject){

        resolve({code:200,data:'ok'})

}).then(function(res){
    console.log(res)
})

如果resolve函数是立即执行而不是延时的话,那再往缓存数组里面丢就没意义了,这种情况我们需要在then函数内部单独判断一下:

myPromise.prototype.then = function(onFulfilled,onRejected){
    let self = this;
    if(self.status === 'pending'){
        self.onFulfilledCallbacks.push(function(){
            onFulfilled(self.value)
        })
        self.onRejectedCallbacks.push(function(){
            onRejected(self.reason)
        })
    }
    //立即执行的情况
    if(self.status==='fulfilled'){
        onFulfilled(self.value)
    }
   //立即执行的情况
    if(self.status === 'rejected'){
        onRejected(self.value)
    }

}

第六步:完整版

function myPromise(callback){
    var self = this;
    self.status = 'pending'
    self.onFulfilledCallbacks = []
    self.onRejectedCallbacks = []
    self.value = null
    self.reason = null
    function resolve(value){
        if(self.status === 'pending'){
            self.status = 'fulfilled'
            self.value = value;
            self.onFulfilledCallbacks.forEach(fn=>fn())

        }
    }
    function reject(reason){
        if(self.status === 'pending'){
            self.status = 'rejected'
            self.reason = reason;
            self.onRejectedCallbacks.forEach(fn=>fn())
        }
    }
    try{
        callback(resolve,reject) //执行高阶函数
    }catch(err){
        reject(err)
    }
}

myPromise.prototype.then = function(onFulfilled,onRejected){
    let self = this;
    if(self.status === 'pending'){
        self.onFulfilledCallbacks.push(function(){
            onFulfilled(self.value)
        })
        self.onRejectedCallbacks.push(function(){
            onRejected(self.reason)
        })
    }
    if(self.status==='fulfilled'){
        onFulfilled(self.value)
    }
    if(self.status === 'rejected'){
        onRejected(self.value)
    }

}

new myPromise(function(resolve,reject){

        resolve({code:200,data:'ok'})

}).then(function(res){
    console.log(res)
})

当然真实的promise比这复杂的多,手写的意义在于加深理解,而不是炫技,重复创造是毫无意义的。

相关文章

  • 手写Promise

    手写 Promise 我们会通过手写一个符合 Promise/A+ 规范的 Promise 来深入理解它,并且手写...

  • 手写 Promise 系列 --- 3

    在前两篇(手写 Promise 系列 --- 1)和(手写 Promise 系列 ---2) 中,达成了3个目标 ...

  • 手写Promise

    $ 正常的promise用法   $ 手写的Promise   # 测试可行性

  • 手写promise

    手写promise 带大家手写一个 promis。在手写之前我会先简单介绍一下为什么要使用promise、prom...

  • 纯手写实现自己的nodejs promise 库

    纯手写实现自己的nodejs promise 库什么是Promise?promise 链Async/Await后续...

  • 手写基础 promise

    1. 前言 玩下吧 手写 promise,看看能写成啥样 2. promise 基础结构 3. 手写`promi...

  • 手写 Promise

    一、Promise 是一个异步操作返回的对象,用来传递异步操作的消息。 Promise 介绍和使用详见: 认识并使...

  • 手写Promise

  • 手写Promise

    Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。 这篇博客有关于P...

  • 手写promise

    本章节纯粹是对promise手写实现。如果不了解promise自行了解再来学习本章知识。promise初体验首先,...

网友评论

    本文标题:手写promise

    本文链接:https://www.haomeiwen.com/subject/nahouhtx.html