0%

手撕Promise

Promise

  • Promise的A+标准

    • 术语
      • promise:是一个拥有 then 方法的对象或函数,其行为符合本规范
      • thenable:是一个定义了 then 方法的对象或函数。这个主要是用来兼容一些老的Promise实现,只要一个Promise实现是thenable,也就是拥有then方法的,就可以跟Promises/A+兼容。
      • value:指reslove出来的值,可以是任何合法的JS值(包括 undefined , thenable 和 promise等)
      • exception:异常,在Promise里面用throw抛出来的值
      • reason:拒绝原因,是reject里面传的参数,表示reject的原因
    • Promise状态
      • pending: 一个promise在resolve或者reject前就处于这个状态。
      • fulfilled: 一个promise被resolve后就处于fulfilled状态,这个状态不能再改变,而且必须拥有一个不可变的值(value)。
      • rejected: 一个promise被reject后就处于rejected状态,这个状态也不能再改变,而且必须拥有一个不可变(引用不变)的拒绝原因(reason)。
    • then方法
      • 一个promise必须拥有一个then方法来访问他的值或者拒绝原因。then方法有两个参数:
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        promise.then(onFulfilled, onRejected)
        //onFulfilled 和 onRejected 都是可选参数。
        //如果 onFulfilled 不是函数,其必须被忽略
        //如果 onRejected 不是函数,其必须被忽略

        //如果 onFulfilled 是函数:
        //当 promise 执行结束后其必须被调用,其第一个参数为 promise 的终值value
        //在 promise 执行结束前其不可被调用
        //其调用次数不可超过一次

        //如果 onRejected 是函数:
        //当 promise 被拒绝执行后其必须被调用,其第一个参数为 promise 的拒因reason
        //在 promise 被拒绝执行前其不可被调用
        //其调用次数不可超过一次
    • 多次调用
      • then 方法可以被同一个 promise 调用多次
      • 当 promise 成功执行时,所有 onFulfilled 需按照其注册顺序依次回调
      • 当 promise 被拒绝执行时,所有的 onRejected 需按照其注册顺序依次回调
    • 返回

      • then 方法必须返回一个 promise对象

      • promise2 = promise1.then(onFulfilled, onRejected);

        • 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行 Promise 解决过程:[[Resolve]](promise2, x)
        • 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e
        • 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
        • 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因
    • 剩下的标准在代码里有所体现
  • 手写A+标准的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
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    //872 passing!
    var PENDING = 'pending';
    var FULFILLED = 'fulfilled';
    var REJECTED = 'rejected';
    function MyPromise(fn) {
    this.status = PENDING; //初始状态为pending
    this.value = null; //初始value为null
    this.reason = null; //初始reason为null

    this.onFulfilledCallbacks = []; //onFulfilled事件中心
    this.onRejectedCallbacks = []; //onRejected事件中心

    var that = this; //这个that是MyPromise中的this
    // 根据规范
    //resolve把status改为fulfilled,
    //reject把status改为rejected

    //resolve相当于发布一个成功事件
    function resolve(value) {
    if (that.status === PENDING) {
    that.status = FULFILLED;
    that.value = value;
    that.onFulfilledCallbacks.map((callback) => callback(that.value));
    }
    }
    //rejected相当于发布一个失败事件
    function rejected(reason) {
    if (that.status === PENDING) {
    that.status = REJECTED;
    that.reason = reason;
    that.onRejectedCallbacks.map((callback) => callback(that.reason));
    }
    }

    //如果有错误,马上捕获
    try {
    fn(resolve, rejected);
    } catch (err) {
    rejected(err);
    }
    }

    function resolvePromise(promise, x, resolve, reject) {
    //如果promise和x指向同一对象,抛出TypeError错误,并拒绝执行
    if (promise === x)
    return reject(new TypeError('resolvePromise: promise and x are the same!'));
    if (x instanceof MyPromise) {
    //如果x也是一个promise,那么继续执行,获取最终状态
    x.then(function (res) {
    resolvePromise(promise, res, resolve, reject);
    }, reject);
    } else if (typeof x === 'object' || typeof x === 'function') {
    //如果x不是一个promise
    if (x === null) {
    return resolve(x);
    }

    try {
    var then = x.then;
    } catch (err) {
    return reject(err);
    }

    //如果then是函数
    if (typeof then === 'function') {
    var called = false;
    try {
    then.call(
    x,
    function (y) {
    if (called) return;
    called = true;
    resolvePromise(promise, y, resolve, reject);
    },
    function (y) {
    if (called) return;
    called = true;
    reject(y);
    }
    );
    } catch (err) {
    //调用then方法抛出了异常

    //如果called已经为true,则不需要管then的执行情况,直接忽略
    if (called) return;
    reject(err);
    }
    } else {
    resolve(x);
    }
    } else {
    resolve(x);
    }
    }

    //then方法可以链式调用
    //a+规范中规定API为promise.then(onFulfilled, onRejected)
    //then方法放在prototype上
    MyPromise.prototype.then = function (onFulfilled, onRejected) {
    var that = this;

    //a+规范约定
    //若onFulfilled不是函数,则忽略
    //若onRejected不是函数,则忽略
    //这里的忽略不是什么都不做
    //对于onFulfilled来说,我们提供一个函数,将value原封不懂返回
    //对于onRejected来说,throw一个ERROR出去

    var realOnFulfilled = onFulfilled;
    if (typeof onFulfilled !== 'function') {
    realOnFulfilled = function (value) {
    return value;
    };
    }

    var realOnRejected = onRejected;
    if (typeof onRejected !== 'function') {
    realOnRejected = function (err) {
    throw err;
    };
    }

    //a+规范规定
    //then方法必须返回一个Promise对象

    //如果 onFulfilled
    //或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e
    if (this.status === PENDING) {
    //这里有订阅发布模式的思想
    var promise2 = new MyPromise(function (resolve, reject) {
    that.onFulfilledCallbacks.push(function () {
    setTimeout(function () {
    try {
    var x = realOnFulfilled(that.value);
    resolvePromise(promise2, x, resolve, reject);
    } catch (err) {
    reject(err);
    }
    }, 0);
    }); //注册事件
    that.onRejectedCallbacks.push(function () {
    setTimeout(function () {
    try {
    var x = realOnRejected(that.reason);
    resolvePromise(promise2, x, resolve, reject);
    } catch (err) {
    reject(err);
    }
    }, 0);
    }); //注册事件
    });
    return promise2;
    }

    //如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
    if (this.status === FULFILLED) {
    var promise2 = new MyPromise(function (resolve, reject) {
    setTimeout(function () {
    try {
    if (typeof onFulfilled !== 'function') {
    resolve(that.value);
    } else {
    var x = realOnFulfilled(that.value);
    resolvePromise(promise2, x, resolve, reject);
    }
    } catch (err) {
    reject(err);
    }
    }, 0);
    });
    return promise2;
    }

    //如果onRejected 不是函数且 promise1 拒绝执行, promise2必须拒绝并返回相同的拒因
    //如果onRejected 是函数且promise1拒绝执行, promise2应该resolve
    if (this.status === REJECTED) {
    var promise2 = new MyPromise(function (resolve, reject) {
    setTimeout(function () {
    try {
    if (typeof onRejected !== 'function') {
    reject(that.reason);
    } else {
    var x = realOnRejected(that.reason);
    resolvePromise(promise2, x, resolve, reject);
    }
    } catch (err) {
    reject(err);
    }
    }, 0);
    });
    return promise2;
    }
    };