实现一个简单的promise

592 阅读4分钟

Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。

  • promise有三种状态:状态一旦改变就不会再发生改变
    • pending:初始状态,不是成功或失败状态
    • fulfilled:成功状态
    • rejected:失败状态

简单使用promise

  • 使用promise实现异步调用和链式调用
   let p = new Promise((resolve,reject)=> {
        resolve('成功')      // 成功的执行 then执行
        // reject('失败')    // 失败的执行 catch执行
    })
      console.log(p);
    p.then((res) => {
        console.log(res);     // 成功
        return '下一次执行then'
    }).then(res => {
        console.log(res);    // 下一次执行then
    }).chatch(err => {
        console.log(err)
    })

then执行的时候,实现链式调用时,需要return出当前的需要的结果,会把当前return出的结果当作promise的链式调用的下一个then的回调函数的参数

输出的的结果:

    // promise的实例
Promise {<fulfilled>: 'promise的实例'}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[PromiseResult]]: "promise的实例"

手写promise

定义promise

使用promise知道,实例上的有PromiseState表示promise的状态,PromiseResult表示promise的实例返回的结果,回调函数具备两个参数resolve和reject,两个参数均为函数。

 function myPromise(fn) {
        this.PromiseState = 'pending'     // 定义初始状态
        this.PromiseResult = undefined
        var resolve = function() {

        }
        var reject = function() {

        }
        if(fn) {
            fn(resolve,reject)
        }
    }
    var p = new myPromise()
    console.log(p);
  • promise的只能输出一个结果,是then或者是catch
  • 定义两次输出状态和结果
    var _this = this   // 保存this的指向,使它始终指向这个函数本身
    var resolve = function (val) {
        if (_this.PromiseState = 'pending') {
            _this.PromiseState = 'fulfilled'   // 如果直接调用this,this指向window
            _this.PromiseResult = val
        }
    }
    var reject = function (errVal) {
        if (_this.PromiseState = 'pending') {
            _this.PromiseState = 'rejected'
            _this.PromiseResult = errVal
        }
    }

then方法的实现

  • 使用promise时,每次调用then都会跟在这个实例方法的后面,这样可以实现then的链式调用
  • then中的函数也是一个回调函数,所以需要定义这个回调函数
this.thenCallback = undefined   // 定义一个函数。用来注册then中的callback
var resolve = function (val) {
    if (_this.PromiseState = 'pending') {
        _this.PromiseState = 'fulfilled'   // 如果直接调用this,this指向window
        _this.PromiseResult = val
        // 为什么变成异步执行(先执行then中的函数,给thenCallback赋值,异步执行,再返回执行这)
         setTimeout(function () {
                    if (_this.thenCallback) {
                        _this.thenCallback(value)
                    }
                })
    }
}
myPromise.prototype.then = function(callback) {
    this.thenCallback = function (value) {  // 现在的this指向的是myPromise实例
            callback(value)
        }
}

实现then的链式调用

  • then可以不停的then下去,实现链式调用
    myPromise.prototype.then = function(callback) {
        var _this = this
       // 链式调用,再次调用这个myPromise方法
        return new myPromise(function(resolve,reject) {
            _this.thenCallback = function (value) { // 现在的this指向的是myPromise实例
                var res = callback(value)
                resovle(res)
            }
        })     
    }

实现catch方法

  • catch是直接结果为错误,只执行一次,寻找错误执行结果
// 定义一个函数对象,用来注册catch中的callback
      this.catchCallback = undefined
        var reject = function (errVal) {
            if (_this.PromiseState = 'pending') {
                _this.PromiseState = 'rejected'
                _this.PromiseResult = errVal
                setTimeout(function () { // 为什么变成异步执行(先执行then中的函数,给catchCallback赋值,异步执行,再返回执行这)
                    if (_this.catchCallback) {
                        _this.catchCallback(errVal)
                    } else if (_this.thenCallback) {
                        _this.thenCallback(errVal)
                    }
                })

            }

        }
    myPromise.prototype.catch = function (callback) {
        var _this = this
        return new myPromise(function (resovle, reject) {
            _this.catchCallback = function (errVal) { // 现在的this指向的是myPromise实例
                var res = callback(errVal)
                reject(res)
            }
        })
    }

全部代码

    function myPromise(fn) {
        this.PromiseState = 'pending'
        this.PromiseResult = undefined
        var _this = this
        this.thenCallback = undefined
        this.catchCallback = undefined
        var resolve = function (val) {
            if (_this.PromiseState = 'pending') {
                _this.PromiseState = 'fulfilled'
                _this.PromiseResult = val
                setTimeout(function () { // 为什么变成异步执行(先执行then中的函数,给thenCallback赋值,异步执行,再返回执行这)
                    if (_this.thenCallback) {
                        _this.thenCallback(val)
                    }
                })
            }
        }
        var reject = function (errVal) {
            if (_this.PromiseState = 'pending') {
                _this.PromiseState = 'rejected'
                _this.PromiseResult = errVal
                setTimeout(function () {
                    if (_this.catchCallback) {
                        _this.catchCallback(errVal)
                    } else if (_this.thenCallback) {
                        _this.thenCallback(errVal)
                    }
                })

            }

        }
        if (fn) {
            fn(resolve, reject)
        }
    }
    myPromise.prototype.then = function (callback) {
        var _this = this
        return new myPromise(function (resolve, reject) {
            _this.thenCallback = function (value) { // 现在的this指向的是myPromise实例
                // 回调的函数promise的状态为rejected
                if (_this.PromiseState === 'rejected') {
                    reject(value)
                } else {
                    var res = callback(value)
                    resolve(res)
                }
            }
        })

    }
    myPromise.prototype.catch = function (callback) {
        var _this = this
        return new myPromise(function (resovle, reject) {
            _this.catchCallback = function (errVal) { // 现在的this指向的是myPromise实例
                var res = callback(errVal)
                reject(res)
            }
        })
    }
    var p = new myPromise(function (resolve, reject) {
        // resolve('then执行')
        reject('catch执行')
    })
    console.log(p);
    p.then(function (res) {
        console.log(res);
        return 111
    }).then(function (res) {
        console.log(res);
    }).catch(function (err) {
        console.log(err);
    })

链式调用的问题

进行链式调用,下一个then的回调函数的参数需要上一个return出去才能拿到,否则回报underfined

// promise
   let p = new Promise((resolve,reject)=> {
        resolve('1')
    })
    p.then(res => {
        console.log(res);
        return new Promise((resolve,reject)=> {
        resolve('2')
    })
    // return '2'    //两次的结果只可以
    }).then(res => {
        console.log(res);     // 2
    })
  • 在手写的这个myPromise中,可以直接return获取,不可以重新把他实例化
    var p = new myPromise(function (resolve, reject) {
        resolve('then执行')
        // reject('catch执行')
    })
    console.log(p);
    p.then(function (res) {
        console.log(res);
        return new myPromise(function (resolve, reject) {
        resolve('then执')
        // reject('catch执行')
        })               // 获取到的时这个实例化对象
        // return 111    // 可以直接获取到111
    }).then(function (res) {
        console.log(res);
    }).catch(function (err) {
        console.log(err);
    })

可以简写的形式使用myPromise.resolve()的调用

            // 改造代码
            var resolve = function (val) {
            if (_this.PromiseState = 'pending') {
                _this.PromiseState = 'fulfilled'
                _this.PromiseResult = val
                if (val instanceof myPromise) {
                    val.then(function (res) {
                        setTimeout(function () { 
                            if (_this.thenCallback) {
                                _this.thenCallback(res)
                            }
                        })
                    })
                } else {
                    setTimeout(function () { 
                        if (_this.thenCallback) {
                            _this.thenCallback(val)
                        }
                    })
                }
            }
        }
          myPromise.resolve = function (res) {
            return new myPromise(function (resolve, reject) {
            resolve(res)
        })
    }
    var p = new myPromise(function (resolve, reject) {
        resolve('then执行')
        // reject('catch执行')
    })
    console.log(p);
    p.then(function (res) {
        console.log(res);
       // return 'then执行2'
       return myPromise.resolve('then执行2')
    }).then(function (res) {
        console.log(res);    // then执行2
    }).catch(function (err) {
        console.log(err);
    })

promise还有好多东西,比如说链式调用的中断allrace等等,这些功能的实现都没有写,只完成了一个最简单的thencatchthen的链式调用

这是本人第一次写博客,也许会有没说明白的地方,和一些错误的地方,也希望大家也可以指点出来。