Promise学习笔记-三(resolve)

1,107 阅读3分钟

在实例化Promise时,resolve方法传入的参数可分为三种:

  1. 当前promise对象自身作为参数传入
  2. 传入一个简单数据类型值,如:string、boolean、number等
  3. 传入一个对象或者function

resolve方法源码

function resolve (self, newValue) {
    // 将自身作为参数传入实例化时中的resolve,调用reject方法,并把state设为2
    if (newValue === self) {
        return reject(self,
            new TypeError('A promise cannot be resolved with itself') 
        )
    }
    // 将一个promise对象或者function作为参数传入
    if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
        var then = getThen(newValue)
        // newValue是一个promise对象时,将状态state设置为3,value设为传入的promise对象
        if (then === self.then && newValue instanceof Promise) {
            self._state = 3
            self._value = newValue
            final(self)
            return
        } else if (typeof then === 'function') {
            doResolve(then.bind(newValue), self)
            return
        }
    }
    // newValue的值是一个简单数据类型,直接输出值,并把状态修改为1
    self._state = 1
    self._value = newValue
    final(self)
}

参数为当前promise对象自身

当前promise对象自身作为参数传入resolve方法时,resolve的内部处理,会直接抛出类型错误:A promise cannot be resolved with itself。上代码:

let promise = new Promise(function (resolve, reject) {
    setTimeout(function () {
        resolve(promise)
    })
})

接下来在,doResolve方法中debugger一下,运行过程如下:

resolve传入自身.gif

同过debugger可以看到,把当前promise对象自身作为参数传入之后,在resolve内部会做一个newValue和self的一个比较结果为true,所以程序会拒绝往下执行,抛出类型错误。

传入一个简单数据类型

实例化时resolve传入一个简单数据类型值时,不会走以上两个判断,直接将state设置为1,value的值设置为newValue,完成程序执行,输出结果。

传入一个对象或function

  • 传入一个对象

    实例化传入对象时,首先通过getThen方法对newValue值进行处理,给newValue添加then属性,getThen源码:

    function getThen(obj) {
        try {
            return obj.then
        } catch (ex) {
            LAST_ERROR = ex
            return IS_ERROR
        }
    }
    

    通过getThen方法添加then属性之后,实际得到的是promise原型上的then方法,通过then === self.then判断是否为true,如果为true再通过newValue instanceof Promise确定传入的newValue是否是一个Promise对象。符合这两个条件之后,将state设置为3,value设置为传入的newValue,也就是传入的promise对象。栗子代码:

    let promise2 = new Promise(function (resolve, reject) {
        resolve('传入的promise对象')
    })
    let promise = new Promise(function (resolve, reject) {
        resolve(promise2)
    }).then(res => {
        console.log(res) // 传入的promise对象
    })
    

    在执行完resolve之后,在调用promise的原型方法then时,在handle执行时,实际上就转化成了promise2实例的一系列的执行了。看一下handle都做了什么?代码如下:

    function handle (self, deferred) {
        // 如果当前执行状态为3,把当前promsie对象转换为传入的promise对象
        while(self._state === 3) {
            self = self._value
        }
        if (self._state === 0 ) {
            ...
           return
        }
        handleResolve(self, deferred)
    }
    

    由handle的代码可以看出,在state值为3时,把当前的promise对象设置为传入的promise对象。也就是可以达到处理上一个异步操作的结果,即在实例promise的then方法中输出的是实例promise2的处理结果。

  • 传入一个function

    传入一个function时,在getThen方法时,then的值为undefined。所以在**typeof then === 'function'**时为false,不会走里面的代码块,所以直接将state值设置为1,value设置为newValue,通过then输出结果。栗子代码:

    let promise = new Promise(function (resolve, reject) {
        resolve(function () {})
    }).then(res => {
        console.log(res) // f () {}
    })