# 参考链接

Promise规范 Promises/A+ 规范 你以为我真的让你手写Primise吗? 根据Promises/A+规范实现Promise(上) promises-aplus-tests 测试手写promise过程 手写一个Promise/A+,完美通过官方872个测试用例

const FULFILLED = 'fullfilled';
const REJECTED = 'rejected';
const PENDING = 'pending';

function isFunction(value) {
    return typeof value === 'function';
}

function MyPromise(executor) {
    if(!isFunction(executor)) return new TypeError('The argument should a function');
    this.value = void 0;
    this.reason = void 0;
    this.status = PENDING;
    this.onfulfilledList = [];
    this.onrejectedList = [];
    const resolve = (value) => {
        if(value instanceof MyPromise) return value.then(resolve, reject);
        setTimeout(() => {
            if(this.status === PENDING) {
                this.status = FULFILLED;
                this.value = value;
                this.onfulfilledList.forEach(cb => {
                    cb(this.value)
                })
            }
        }, 0)
    }
    const reject = (value) => {
        setTimeout(() => {
            if(this.status === PENDING) {
                this.status = REJECTED;
                this.reason = value;
                this.onrejectedList.forEach(cb => {
                    cb(this.reason)
                })
            }
        }, 0)
    }
    try {
        executor(resolve, reject)
    } catch (error) {
        reject(error)
    }
}


function resolvePromise(promise, result, resolve, reject) {
    if (promise === result) reject(new TypeError('不能循环引用'));
    
    let consumed = false, thenable = null;
    if (result instanceof MyPromise) {
        if(result.status === PENDING) {
            result.then(data => {
                resolvePromise(promise, data, resolve, reject)
            }, reject)
        } else {
            result.then(resolve, reject)
        }
        return;
    }
    let isComplexResult = target => (typeof result === 'function' || typeof result === 'object') && (target !== null);
    if (isComplexResult(result)) {
        try {
            thenable = result.then;
            if(isFunction(thenable)) {
                thenable.call(result, data => {
                    if(consumed) return;
                    consumed = true;
                    return resolvePromise(promise, data, resolve, reject)
                }, err => {
                    if(consumed) return;
                    consumed = true;
                    return reject(err)
                })
            } else {
                return resolve(result);
            }
        } catch (error) {
            if(consumed) return;
            consumed = true;
            return reject(error)
        }
    } else {
        return resolve(result);
    }
}
MyPromise.prototype.then = function(onfulfilled, onrejected) {
    onfulfilled = isFunction(onfulfilled) ? onfulfilled : data => data;
    onrejected = isFunction(onrejected) ? onrejected : err => { throw err; };
    let promise2;
    if(this.status === FULFILLED) {
        return promise2 = new MyPromise((resolve, rejected) => {
            setTimeout(() => {
                try {
                    let result = onfulfilled(this.value);
                    resolvePromise(promise2, result, resolve, rejected);
                } catch (error) {
                    rejected(error)
                }
            }, 0)
        })
    }
    if(this.status === REJECTED) {
        return promise2 = new MyPromise((resolve, rejected) => {
            setTimeout(() => {
                try {
                    let result = onrejected(this.reason);
                    resolvePromise(promise2, result, resolve, rejected);
                } catch (error) {
                    rejected(error)
                }
            }, 0)
        })
    }
    if(this.status === PENDING) {
        return promise2 = new MyPromise((resolve, rejected) => {
            this.onfulfilledList.push((value)=> {
                try {
                    let result = onfulfilled(value);
                    resolvePromise(promise2, result, resolve, rejected);
                } catch (error) {
                    rejected(error)
                }
            })
            this.onrejectedList.push((value)=> {
                try {
                    let result = onrejected(value);
                    resolvePromise(promise2, result, resolve, rejected);
                } catch (error) {
                    rejected(error)
                }
            })
        })
    }
}
MyPromise.defer = MyPromise.deferred = function(){
    let dfd = {};
    dfd.promise = new MyPromise((resolve, reject)=>{
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd;
}
module.exports =  MyPromise;
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
最后更新时间: 6/20/2022, 10:48:50 PM