以下是学习promise的一些记录。有些内容来源于网络大牛的个人博客
promise的英文官网:https://promisesaplus.com/

  • promise实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    /**
    * 1: new Promise的时候,需要传递一个executor执行器,执行器立刻执行
    * 2: executor执行器接受两个参数,分别是resolve和reject
    * 3: promise的状态只能从pending到fulfilled(通常会叫resolved)或者是从pending到rejected
    * 4: promise的状态一旦确定,就不会再发生改变
    * 5: promise都有then方法,then接收两个参数,分别是promise成功的回调onFulfilled和promise失败的回调onRejected
    * 6: 如果调用then时,promise已经成功,则执行onFulfilled,并将promise的值作为参数传递进去。如果promise已经失败,那么执行onRejected,并将promise失败的原因作为参数传递进去。如果promise的状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再依次将对应的函数执行
    * 7: then的参数onFulfilled和onRejected可以缺省
    * 8: promise可以then多次,promise的then方法返回一个promise
    * 9: 如果then返回的是一个结果,那么就会把这个结果作为参数,传递给下一个then的成功回调
    * 10:如果then中抛出了异常,那么就会把这个异常作为参数,传递给下一个then的失败的回调
    * 11:如果then返回的是一个promise,那么需要等待这个promise执行完成,如果promise成功,就走下一个then的成功回调,如果失败,那么就走下一个then的失败回调。
    */
    const PENDING = 'pending';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
    function Promise(executor) {
    let self = this;
    self.status = PENDING;
    self.onFulfilled = []; // 将成功的回调放入数组中
    self.onRejected = []; // 将失败的回调放入数组中

    // 实现promiseA+ 2.1。promise必须是以下三个状态之一:pending, fulfilled,rejected
    function resolve(value){
    if (self.status === PENDING) {
    self.status = FULFILLED;
    self.value = value;
    self.onFulfilled.forEach(fn => fn()); // promiseA+ 2.2.6.1。当promise执行完成以后,所有的onFulfilled回调函数,必须按照其最初调用then的顺序依次执行
    }
    }
    function reject(reason) {
    if (self.status === PENDING) {
    self.status = REJECTED;
    self.reason = reason;
    self.onRejected.forEach(fn => fn()); // promiseA+ 2.2.6.2。当 promise 执行被拒绝后,所有 onRejected 回调函数,必须按照其最初调用 then 的顺序依次执行。
    }
    }
    try{
    executor(resolve, reject); // executor执行器接收两个参数,一个是成功时的回调函数,一个是失败时的回调函数
    }catch (e) {
    reject(e) // 如果在执行executor的过程中抛出错误,那么直接将整个promise的状态变成reject
    }
    }

    // promise对象必须提供一个then方法来访问其当前值、最终值或原因
    Promise.prototype.then = function(onFulfilled, onRejected){
    // promiseA+ 2.2.1 onFulfilled 和 onRejected 都是可选参数。
    // promiseA+ 2.2.5 onFulfilled 和 onRejected 必须被作为函数调用
    // promiseA+ 2.2.7.3 如果 onFulfilled 不是函数,并且 promise1 执行完成,promise2 必须成功完成并返回相同的值(value)。
    // promiseA+ 2.2.7.4 如果 onRejected 不是函数,并且 promise1 执行被拒绝,promise2 必须以相同的原因(reason)被拒绝执行。
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};
    let self = this;

    // promiseA+ 2.2.7 promise的then方法必须返回一个promise对象
    let promise2 = new Promise((resolve, reject) => {
    if (self.status === FULLFILLED) {
    // promiseA+ 2.2.2; promiseA+ 2.2.4
    setTimeout(() => {
    try {
    // promiseA+ 2.2.7.1 如果 onFulfilled 或者 onRejected 返回一个值 x ,运行 Promise Resolution Procedure [[Resolve]](promise2, x)
    let x = onFullfiled(self.value);
    resolvePromise(promise2, x, resolve, reject)
    } catch(e) {
    // promiseA+ 2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e,则 promise2 必须拒绝执行,并以 e 作为拒绝的原因
    reject(e)
    }
    })
    } else if (self.status === REJECTED) {
    setTimeout(() => {
    try {
    let x = onRejected(self.reason)
    resolvePromise(promise2, x, resolve, reject)
    } catch (e) {
    reject(e)
    }
    })
    } else if (self.status === PENDING) {
    self.onFullfilled.push(() => {
    setTimeout(() => {
    try{
    let x = onFullfilled(self.value);
    resolvePromise(promise2, x, resolve, reject)
    } catch(e) {
    reject(e)
    }
    })
    });
    self.onRejected.push(() => {
    try {
    let x = onReject(self.reason);
    resolvePromise(promise2, x, resolve, reject);
    } catch (e) {
    reject(e)
    }
    })
    }
    })
    return promise2;
    }

    function resolvePromise(promise2, x, resolve, reject) {
    let self = this;
    // promiseA+ 2.3.1 如果promise和x引用同一个对象,那么以 TypeError 为原因拒绝执行 promise。
    if (promise2 === x) {
    reject(new TypeError('Chaining cycle'))
    }
    if (x && typeof x === 'object' || typeof x === 'function') {
    // promiseA+ 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 都被调用,或者被使用相同的参数调用了多次,则首次调用将被优先采用,其它调用将被忽略。
    let used; // 采用标记来记录是否已经被调用
    try {
    let then = x.then;
    if (typeof then === 'function') {
    // promiseA+ 2.3.3
    then.call(x, (y) => {
    if (used) return;
    used = true;
    resolvePromise(promise2, y, resolve, reject)
    }, (r) => {
    // promiseA+ 2.3.3.2 如果取 x.then 的值时抛出错误 e,则使用 e 为原因拒绝 promise。
    if (used) return;
    used = true;
    reject(r)
    })
    } else {
    // promiseA+ 2.3.3.4 如果 x 不是对象或者函数,以 x 为值完成 promise。
    if (used) return;
    used = true;
    resolve(x)
    }
    } catch(e) {
    // promiseA+ 2.3.3.2 如果取 x.then 的值时抛出错误 e,则使用 e 为原因拒绝 promise。
    if (used) return;
    used = true;
    reject(e);
    }
    } else {
    // promiseA+ 2.3.3.4 如果 then 不是函数,以 x 为值完成 promise。
    resolve(x)
    }
    }
    • promise的其他方法的实现
      以上实现了基本的promise方法,下面我们来实现一些promise提供的其他方法
    • Promise.resolve
      Promise.resolve(value)返回一个给定值解析后的promise对象

      • 如果value是一个thenable对象,返回的promise会采用这个thenable的对象,采用它的最终状态。
      • 如果传入的value本身就是promise对象,那么Promise.resolve将不做任何修改,直接返回该promise
      • 其他情况,直接返回以该值为成功状态的promise对象。
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        Promise.resolve = function(param) {
        if (param instanceof Promise) return param;
        return new Promise((resolve, reject) => {
        if (param && param.then && typeof param.then === 'function') {
        setTimeout(() => {
        param.then(resolve, reject);
        })
        } else {
        resolve(param);
        }
        })
        }
    • Promise.reject

      1
      2
      3
      4
      5
      Promise.reject = function(reason) {
      return new Promise((resolve, reject) => {
      reject(reason)
      })
      }
    • Promise.prototype.catch
      Promise.prototype.catch 用于指定出错时的回调,是特殊的then方法,catch之后,可以继续 .then

      1
      2
      3
      Promise.prototype.catch = function(onRejected){
      return this.then(null, onRejected)
      }
    • Promise.prototype.finally
      不管成功还是失败,都会执行finally中,并且finally之后,还可以继续then。并且会将值原封不动的传递给后面的then.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      Promise.prototype.finally = function(callback){
      return this.then((value) => {
      return Promise.resolve(callback()).then(() => {
      return value;
      })
      }, (err) => {
      return Promise.resolve(callback()).then(() => {
      return err;
      })
      })
      }
    • Promise.all
      Promise.all(promises)返回一个promise对象

      • 如果传入的参数是一个空的可迭代对象,那么此promise对象回调完成(resolve),只有此情况,是同步执行的,其它都是异步返回的。
      • 如果传入的参数不包含任何 promise,则返回一个异步完成.
      • promises 中所有的promise都“完成”时或参数中不包含 promise 时回调完成。
      • 如果参数中有一个promise失败,那么Promise.all返回的promise对象失败
      • 在任何情况下,Promise.all 返回的 promise 的完成状态的结果都是一个数组
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        Promise.all = function(promises){
        return new Promise((resolve, reject) => {
        let index = 0;
        let result = [];
        if (promises.length === 0) {
        resolve(result)
        } else {
        setTimeout(() => {
        function processValue(i, data){
        result[i] = data;
        if (++index === promises.length) {
        resolve(result)
        }
        }
        for (let i = 0; i < promises.length; i++) {
        //promises[i] 可能是普通值
        Promise.resolve(promises[i]).then((data) => {
        processValue(i, data);
        }, (err) => {
        reject(err);
        return;
        });
        }
        })
        }
        })
        }
    • Promise.race
      Promise.race函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。
      如果传的参数数组是空,则返回的 promise 将永远等待。
      如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
    if (promises.length === 0) {
    return;
    } else {
    for (let i = 0; i < promises.length; i++) {
    Promise.resolve(promises[i]).then((data) => {
    resolve(data);
    return;
    }, (err) => {
    reject(err);
    return;
    });
    }
    }
    });
    }