zoukankan      html  css  js  c++  java
  • 手写Promise

    Promise是一个异步编程的解决方案。

    之前的方案是回调函数的方式。优点是指定回调函数的位置更灵活,和解决了回调地狱问题。

    规范是Promise 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
    (function (window) {
    // 三个状态常量
    const PENDING = 'pending', // 等待
    FULFILLED = 'fulfilled', // 成功
    REJECTED = 'rejected'; // 失败
    /**
    * Promise 类
    * @param {Function} excutor 执行器
    */
    function Promise(excutor) {
    // 初始化状态
    this.state = PENDING;
    // 存储数据
    this.data = null;
    // 存储.then的回调函数 {onFulfilled, onRejected}
    // 可能多次.then,所以是一个数据
    this.callbacks = [];

    /**
    * resolve 成功函数
    * @param {*} value 成功的数据
    */
    function resolve(value) {}

    /**
    * reject 失败函数
    * @param {*} reason 失败的原因
    */
    function reject(reason) {}
    try {
    excutor(resolve, reject); // 立即执行 执行器函数
    } catch (error) {
    reject(error); // 异常就直接抛出
    }
    }

    /**
    * 原型对象上的then方法
    * @param {Function} onFulfilled 获取成功的回调函数
    * @param {Function} onRejected 获取失败的回调函数
    * @returns {Promise} 新的Promise对象
    */
    Promise.prototype.then = function (onFulfilled, onRejected) {}

    /**
    * 原型对象上的catch方法
    * @param {Function} onRejected 获取失败的回调函数
    * @returns {Promise} 新的Promise对象
    */
    Promise.prototype.catch = function (onRejected) {}

    /**
    * Promise函数对象的resolve方法
    * @param {*} value
    */
    Promise.resolve = function (value) {}

    /**
    * Promise函数对象的reject方法
    * @param {*} reason
    */
    Promise.reject = function (reason) {}

    /**
    * Promise函数对象的all方法
    * 所有成功才成功,只要一个失败则失败
    */
    Promise.all = function (promises) {}

    /**
    * Promise函数对象的race方法
    * 第一个结束的 成功则成功 失败则失败
    */
    Promise.race = function (promises) {};

    window.Promise = Promise;
    })(window); // IIEF

    执行器的resolve

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    /**
    * resolve 成功函数
    * @param {*} value 成功的数据
    */
    resolve = value => {
    // 检查状态,保证状态只能改变一次
    if (this.state !== PENDING) {
    return;
    }
    // 改状态
    this.state = FULFILLED;
    // 存数据
    this.data = value;
    // 检查回调,如果有,立即执行回调函数
    if (this.callbacks.length > 0) {
    setTimeout(() => {
    this.callbacks.forEach(callbackObj => {
    callbackObj.onFulfilled(this.data);
    });
    });
    }
    }

    执行器的reject,

    复制粘贴resolve,改状态、名字即可。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    /**
    * reject 失败函数
    * @param {*} reason 失败的原因
    */
    reject = reason => {
    // 查状态,保证状态只能改变一次
    if (this.state !== PENDING) {
    return;
    }
    // 改状态
    this.state = REJECTED;
    // 存数据
    this.data = reason;
    // 检查回调,如果有,立即执行回调函数
    if (this.callbacks.length > 0) {
    setTimeout(() => {
    this.callbacks.forEach(callbackObj => {
    callbackObj.onRejected(this.data);
    });
    });
    }
    }

    原型对象上的then 方法

    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
    /**
    * 原型对象上的then方法
    * @param {Function} onFulfilled 获取成功的回调函数
    * @param {Function} onRejected 获取失败的回调函数
    * @returns {Promise} 新的Promise对象
    */
    Promise.prototype.then = function (onFulfilled, onRejected) {
    // 保存当前Promise的this
    const that = this;
    // 返回一个新的Promise
    return new Promise((resolve, reject) => {
    if (that.state = FULFILLED) {
    // 立即异步执行成功的回调函数
    setTimeout(() => {
    /**
    * 返回Promise的结果由onFulfilled或onRejected执行结果决定
    * 情况1.抛出异常 返回Promise的结果为异常,reason为异常
    * 情况2.返回的是Promise,返回Promise的结果就是这个Promise的结果
    * 情况3.返回的不是Promise,返回的Promise为成功,value就是返回值
    */
    try {
    const result = onFulfilled(that.data);
    if (result instanceof Promise) {
    // 情况2
    result.then(resolve, reject);
    } else {
    // 情况3
    resolve(result);
    }
    } catch (error) {
    // 情况1
    reject(error);
    }
    });
    } else if (that.state = REJECTED) {
    // 立即异步执行失败的回调函数
    setTimeout(() => {
    /**
    * 返回Promise的结果由onFulfilled或onRejected执行结果决定
    * 情况1.抛出异常 返回Promise的结果为异常,reason为异常
    * 情况2.返回的是Promise,返回Promise的结果就是这个Promise的结果
    * 情况3.返回的不是Promise,返回的Promise为成功,value就是返回值
    */
    try {
    const result = onRejected(that.data);
    if (result instanceof Promise) {
    // 情况2
    result.then(resolve, reject);
    } else {
    // 情况3
    resolve(result);
    }
    } catch (error) {
    // 情况1
    reject(error);
    }
    });
    } else { // that.state = PENDING
    // 保存回调函数到callbacks中去
    // that.callbacks.push({
    // onFulfilled, onRejected
    // }); // 直接赋值onFulfilled, onRejected
    // 没有机会改变Promise的状态,所以要像成功失败那样再包一层函数
    that.callbacks.push({
    onFulfilled: handle(onFulfilled),
    onRejected: handle(onRejected)
    });
    }
    });
    }

    封装handle

    在.then方式中成功和失败的处理很类似,所以封装出来

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    const handle = callback => {
    /**
    * 返回Promise的结果由onFulfilled或onRejected执行结果决定
    * 情况1.抛出异常 返回Promise的结果为异常,reason为异常
    * 情况2.返回的是Promise,返回Promise的结果就是这个Promise的结果
    * 情况3.返回的不是Promise,返回的Promise为成功,value就是返回值
    */
    try {
    const result = callback(that.data);
    if (result instanceof Promise) {
    // 情况2
    result.then(resolve, reject);
    } else {
    // 情况3
    resolve(result);
    }
    } catch (error) {
    // 情况1
    reject(error);
    }
    }

    优化后的then方法

    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
    /**
    * 原型对象上的then方法
    * @param {Function} onFulfilled 获取成功的回调函数
    * @param {Function} onRejected 获取失败的回调函数
    * @returns {Promise} 新的Promise对象
    */
    Promise.prototype.then = function (onFulfilled, onRejected) {
    // 设置回调函数默认值(必须是函数),Promise继续传递的保障
    onResolved = typeof onResolved === 'function' ? onResolved : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };

    // 保存当前Promise的this
    const that = this;
    // 返回一个新的Promise
    return new Promise((resolve, reject) => {
    const handle = callback => {
    /**
    * 返回Promise的结果由onFulfilled或onRejected执行结果决定
    * 情况1.抛出异常 返回Promise的结果为异常,reason为异常
    * 情况2.返回的是Promise,返回Promise的结果就是这个Promise的结果
    * 情况3.返回的不是Promise,返回的Promise为成功,value就是返回值
    */
    try {
    const result = callback(that.data);
    if (result instanceof Promise) {
    // 情况2
    result.then(resolve, reject);
    } else {
    // 情况3
    resolve(result);
    }
    } catch (error) {
    // 情况1
    reject(error);
    }
    }
    if (that.state = FULFILLED) {
    // 立即异步执行成功的回调函数
    setTimeout(() => {
    handle(onFulfilled);
    });
    } else if (that.state = REJECTED) {
    // 立即异步执行失败的回调函数
    setTimeout(() => {
    handle(onRejected);
    });
    } else { // that.state = PENDING
    // 保存回调函数到callbacks中去
    that.callbacks.push({
    onFulfilled: handle(onFulfilled),
    onRejected: handle(onRejected)
    });
    }
    });
    }

    原型对象上的catch方法

    1
    2
    3
    4
    5
    6
    7
    8
    /**
    * 原型对象上的catch方法
    * @param {Function} onRejected 获取失败的回调函数
    * @returns {Promise} 新的Promise对象
    */
    Promise.prototype.catch = function (onFulfilled, onRejected) {
    return this.then(undefined, onRejected);
    }

    函数对象上的resolve和reject方法

    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函数对象的resolve方法
    * 如果收到的是个Promise对象,那么传递下去
    * 如果是一个值,就直接返回值
    * @param {*} value
    * @returns Promise
    */
    Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
    if (value instanceof Promise) {
    value.then(resolve, reject);
    } else {
    resolve(value);
    }
    })
    }

    /**
    * Promise函数对象的reject方法
    * @param {*} reason
    * @returns Promise
    */
    Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
    reject(reason);
    });
    }

    函数对象上的all和race方法

    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
    /**
    * Promise函数对象的all方法
    * 所有成功才成功,只要一个失败则失败
    * @param {Array<Promise>} promises promise的数组
    */
    Promise.all = function (promises) {
    // 定义返回结果数组的长度,因为返回的数组要按照传入的数组
    const values = new Array(promises.length);
    // 计算器变量,保证 所有成功才成功
    let resolvedCount = 0;
    return new Promise((resolve, reject) => {
    promises.forEach((promise, index) => {
    P.resolve(promise).then(
    value => {
    // 计数器增加
    resolvedCount++;
    // 按数组顺序 塞进返回结果数组
    values[index] = value;
    if (resolvedCount === promises.length) {
    resolve(values);
    }
    },
    reason => {
    reject(reason);
    }
    );
    });
    });
    }

    /**
    * Promise函数对象的race方法
    * 第一个结束的 成功则成功 失败则失败
    * @param {Array<Promise>} promises promise的数组
    */
    Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
    promises.forEach(promise => {
    Promise.resolve(promise).then(
    value => {
    resolve(value);
    },
    reason => {
    reject(reason);
    }
    );
    });
    });
    };

    完整的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
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    (function (window) {
    // 三个状态常量
    const PENDING = 'pending', // 等待
    FULFILLED = 'fulfilled', // 成功
    REJECTED = 'rejected'; // 失败
    /**
    * Promise 类
    * @param {Function} excutor 执行器
    */
    const Promise = (excutor) => {
    // 初始化状态
    this.state = PENDING;
    // 存储数据
    this.data = null;
    // 存储.then的回调函数 {onFulfilled, onRejected}
    // 可能多次.then,所以是一个数据
    this.callbacks = [];

    /**
    * resolve 成功函数
    * @param {*} value 成功的数据
    */
    resolve = value => {
    // 检查状态,保证状态只能改变一次
    if (this.state !== PENDING) {
    return;
    }
    // 改状态
    this.state = FULFILLED;
    // 存数据
    this.data = value;
    // 检查回调,如果有,立即执行回调函数
    if (this.callbacks.length > 0) {
    setTimeout(() => {
    this.callbacks.forEach(callbackObj => {
    callbackObj.onFulfilled(this.data);
    });
    });
    }
    }

    /**
    * reject 失败函数
    * @param {*} reason 失败的原因
    */
    reject = reason => {
    // 查状态,保证状态只能改变一次
    if (this.state !== PENDING) {
    return;
    }
    // 改状态
    this.state = REJECTED;
    // 存数据
    this.data = reason;
    // 检查回调,如果有,立即执行回调函数
    if (this.callbacks.length > 0) {
    setTimeout(() => {
    this.callbacks.forEach(callbackObj => {
    callbackObj.onRejected(this.data);
    });
    });
    }
    }
    try {
    excutor(resolve, reject); // 立即执行 执行器函数
    } catch (error) {
    reject(error); // 异常就直接抛出
    }
    }

    /**
    * 原型对象上的then方法
    * @param {Function} onFulfilled 获取成功的回调函数
    * @param {Function} onRejected 获取失败的回调函数
    * @returns {Promise} 新的Promise对象
    */
    Promise.prototype.then = function (onFulfilled, onRejected) {
    // 设置回调函数默认值(必须是函数),Promise继续传递的保障
    onResolved = typeof onResolved === 'function' ? onResolved : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };

    // 保存当前Promise的this
    const that = this;
    // 返回一个新的Promise
    return new Promise((resolve, reject) => {
    const handle = callback => {
    /**
    * 返回Promise的结果由onFulfilled或onRejected执行结果决定
    * 情况1.抛出异常 返回Promise的结果为异常,reason为异常
    * 情况2.返回的是Promise,返回Promise的结果就是这个Promise的结果
    * 情况3.返回的不是Promise,返回的Promise为成功,value就是返回值
    */
    try {
    const result = callback(that.data);
    if (result instanceof Promise) {
    // 情况2
    result.then(resolve, reject);
    } else {
    // 情况3
    resolve(result);
    }
    } catch (error) {
    // 情况1
    reject(error);
    }
    }
    if (that.state = FULFILLED) {
    // 立即异步执行成功的回调函数
    setTimeout(() => {
    handle(onFulfilled);
    });
    } else if (that.state = REJECTED) {
    // 立即异步执行失败的回调函数
    setTimeout(() => {
    handle(onRejected);
    });
    } else { // that.state = PENDING
    // 保存回调函数到callbacks中去
    that.callbacks.push({
    onFulfilled: handle(onFulfilled),
    onRejected: handle(onRejected)
    });
    }
    });
    }

    /**
    * 原型对象上的catch方法
    * @param {Function} onRejected 获取失败的回调函数
    * @returns {Promise} 新的Promise对象
    */
    Promise.prototype.catch = function (onFulfilled, onRejected) {
    return this.then(undefined, onRejected);
    }

    /**
    * Promise函数对象的resolve方法
    * 如果收到的是个Promise对象,那么传递下去
    * 如果是一个值,就直接返回值
    * @param {*} value
    * @returns Promise
    */
    Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
    if (value instanceof Promise) {
    value.then(resolve, reject);
    } else {
    resolve(value);
    }
    })
    }

    /**
    * Promise函数对象的reject方法
    * @param {*} reason
    * @returns Promise
    */
    Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
    reject(reason);
    });
    }

    /**
    * Promise函数对象的all方法
    * 所有成功才成功,只要一个失败则失败
    * @param {Array<Promise>} promises promise的数组
    */
    Promise.all = function (promises) {
    // 定义返回结果数组的长度,因为返回的数组要按照传入的数组
    const values = new Array(promises.length);
    // 计算器变量,保证 所有成功才成功
    let resolvedCount = 0;
    return new Promise((resolve, reject) => {
    promises.forEach((promise, index) => {
    P.resolve(promise).then(
    value => {
    // 计数器增加
    resolvedCount++;
    // 按数组顺序 塞进返回结果数组
    values[index] = value;
    if (resolvedCount === promises.length) {
    resolve(values);
    }
    },
    reason => {
    reject(reason);
    }
    );
    });
    });
    }

    /**
    * Promise函数对象的race方法
    * 第一个结束的 成功则成功 失败则失败
    * @param {Array<Promise>} promises promise的数组
    */
    Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
    promises.forEach(promise => {
    Promise.resolve(promise).then(
    value => {
    resolve(value);
    },
    reason => {
    reject(reason);
    }
    );
    });
    });
    };

    window.Promise = Promise;
    })(window); // IIEF
  • 相关阅读:
    最优装载(二分答案)
    最小生成树
    hibernate映射实体类查询时数据库空字段赋值给实体类报错的问题
    'hibernate.dialect' must be set when no Connection avalable
    简单了解一下oracle中的显示游标和存储过程
    oracle中的预定异常和自定义异常
    PL/sql中如何声明变量,常量,控制语句及for,loop,while和顺序控制的使用
    简单了解,使用oracle中的索引,表分区
    oracle中序列,同义词的创建
    数据库权限管理
  • 原文地址:https://www.cnblogs.com/lihaijia/p/14556245.html
Copyright © 2011-2022 走看看