zhaoxiaoqiang1
2026-01-04 f1d30d03186c79ca2cbcfe60d6d2ce7d73fba97b
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
// 判断变量否为function
function isFunction(variable) {
    return typeof variable === 'function';
}
 
// 定义promise状态常量
var PENDING = 'PENDING',
    FULFILLED = 'FULFILLED',
    REJECTED = 'REJECTED'
 
/**
 *定义_Promise构造函数
 *
 * @param {*} handle 注册回调方法
 */
function _Promise(handle) {
    if (!isFunction(handle)) {
        throw Error("_Promise构造函数接收函数作为参数");
    }
    this._status = PENDING
    this._value = undefined
    this._fulfilledQueues = []
    this._rejectedQueues = []
    try {
        handle(this._resolve.bind(this), this._reject.bind(this))
    } catch (err) {
        this._reject(err)
    }
}
 
// 重写_Promise原型对象
_Promise.prototype = {
    constructor: _Promise,
    _resolve: function (val) {
        var _this = this
        function run() {
            if (_this._status != PENDING) return;
            _this._status = FULFILLED
            function runFulfilled(value) {
                var cb;
                while (cb = _this._fulfilledQueues.shift()) {
                    cb(value)
                }
            }
            function runRejected(error) {
                var cb;
                while (cb = _this._rejectedQueues.shift()) {
                    cb(error)
                }
            }
            if (val instanceof _Promise) {
                val.then(function (value) {
                    _this._value = value
                    runFulfilled(value)
                }.bind(_this), function (err) {
                    _this._value = err
                    runRejected(err)
                }.bind(_this))
            } else {
                _this._value = val
                runFulfilled(val)
            }
        }
        setTimeout(run, 0)
    },
    _reject: function (err) {
        var _this = this
        if (this._status !== PENDING) return
        function run() {
            _this._status = REJECTED
            _this._value = err
            var cb;
            while (cb = _this._rejectedQueues.shift()) {
                cb(err)
            }
        }
        setTimeout(run, 0)
    },
 
    /**
     *then方法
     *
     * @param {*} onFulfilled 异步成功的回调
     * @param {*} onRejected 异步失败回调
     * @returns 返回新的_Promise实例,支持链式调用
     */
    then: function (onFulfilled, onRejected) {
        var _value = this._value
        var _status = this._status
        var _this = this
        return new _Promise(function (onFulfilledNext, onRejectedNext) {
            function fulfilled(value) {
                try {
                    if (!isFunction(onFulfilled)) {
                        onFulfilledNext(value)
                    } else {
                        var res = onFulfilled(value);
                        if (res instanceof _Promise) {
                            res.then(onFulfilledNext, onRejectedNext)
                        } else {
                            onFulfilledNext(res)
                        }
                    }
                } catch (err) {
                    onRejectedNext(err)
                }
            }
            var rejected = error => {
                try {
                    if (!isFunction(onRejected)) {
                        onRejectedNext(error)
                    } else {
                        var res = onRejected(error);
                        if (res instanceof _Promise) {
                            res.then(onFulfilledNext, onRejectedNext)
                        } else {
                            onFulfilledNext(res)
                        }
                    }
                } catch (err) {
                    onRejectedNext(err)
                }
            }
 
            switch (_status) {
                case PENDING:
                    _this._fulfilledQueues.push(fulfilled)
                    _this._rejectedQueues.push(rejected)
                    break
                case FULFILLED:
                    fulfilled(_value)
                    break
                case REJECTED:
                    rejected(_value)
                    break
            }
        })
    },
 
    /**
     *catch方法
     *
     * @param {*} onRejected 失败时回调方法
     * @returns 返回新的_Promise实例
     */
    catch: function (onRejected) {
        return this.then(undefined, onRejected)
    }
}
 
// _Promise构造函数的部分静态方法
_Promise.resolve = function (value) {
    if (value instanceof _Promise) return value
    return new _Promise(function (resolve) {
        return resolve(value)
    })
}
_Promise.reject = function (value) {
    return new _Promise(function (resolve, reject) {
        return resolve(value)
    })
}
 
/**
 *并发多个异步事件
 *
 * @param {*} list 由_promise对象组成的数组集合
 * @returns 返回新的_promise实例 支持链式调用
 */
_Promise.all = function (list) {
    var _this = this
    return new _Promise(function (resolve, reject) {
        var values = []
        var count = 0
        list.forEach(function (e, i) {
            _this.resolve(e).then(function (res) {
                values[i] = res
                count++
                if (count === list.length) resolve(values);
            }, function (err) {
                reject(err)
            })
        })
    })
}
 
/**
 *不管成功或失败都执行的finally方法
 *
 * @param {*} cb 回调事件
 * @returns 新的promise实例
 */
_Promise.finally = function (cb) {
    return this.then(function (value) {
        return _Promise.resolve(cb()).then(function () { return value; })
    }, function (reason) {
        return _Promise.resolve(cb()).then(function () { throw reason; })
    })
}