SOURCE

// /**
//  * 实现Promise几个步骤
//  * 1. 设置三个状态:pending、rejected、fulfilled
//  * 2. 设置执行函数executor、成功回调函数resolve、失败回调函数reject
//  * 3. 缓存then函数执行值,等待状态改变
//  * 
//  * 下面其实就是一种发布订阅模式
//  * 收集依赖 => 触发通知 => 取出依赖执行 
//  */
const Pending = 'pending';
const Rejected = 'rejected';
const Fulfilled = 'fulfilled';

function resolvePromise(promise2, data, resolve, reject) {
    if (data === promise2) {
        return reject(new TypeError('Chaining cycle is Error'));
    }

    let called = false;
    if ((typeof data === 'object' && data !== null) || typeof data === 'function') {
        try{
            let then = data.then;
            if (typeof then === 'function') {
                then.call(data, v => {
                    if (called)return;
                    called = true;
                    resolvePromise(promise2, v, resolve, reject);
                }, r => {
                    if (called)return;
                    called = true;
                    // 注意这个地方,既然reject就不需要在执行resolvePromse,不再向下传递
                    reject(r);
                });
            } else {
                resolve(data);
            }
        } catch(e){
            if (called) return;
            called = true;
            reject(e);
        } 
    } else {
        console.log('resolvePromise', data);
        // 普通值
        resolve(data);
    }
}

class Promise {
    constructor(executor) {
        this.status = Pending;
        this.value = undefined;
        this.reason = undefined;

        this.resolveList = [];
        this.rejectList = [];   

        let resolve = (value) => {
            if (this.status === Pending) {
                console.log(this.resolveList);
                this.status = Fulfilled;
                this.value = value;
                this.resolveList.forEach(fn => fn());
            }
        }

        let reject = (reason) => {
            if (this.status === Pending) {
                this.status = Rejected;
                this.reason = reason;
                this.rejectList.forEach(fn => fn());
            }
        }

        try {
            executor(resolve, reject);
        } catch(e) {
            reject(e);
        }
    }

    then(onFulfilled, onRejected) {
        // onFulfilled = typeof onFulfilled === 'funciton' ? onFulfilled : v => v;
        // onRejeced = typeof onRejeced === 'function' ? onRejeced : err => { throw err};

        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
            //因为错误的值要让后面访问到,所以这里也要跑出个错误,不然会在之后 then 的 resolve 中捕获
         onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };


        let promise2 = new Promise((resolve, reject) => {
            console.log('promise2', this.status);
            // if (this.status === Fulfilled) {
            //     setTimeout(() => {
            //         try {
                    
            //             const data = onFulfilled(this.value);
            //             console.log(data);
            //             resolvePromise(promise2, data, resolve, reject);
                    
            //         } catch(e) {
            //             reject(e);
            //         }
            //     },0);
                
                
            // }

            if (this.status === Fulfilled) {
                //Promise/A+ 2.2.2
                //Promise/A+ 2.2.4 --- setTimeout
                setTimeout(() => {
                try {
                    //Promise/A+ 2.2.7.1
                    let x = onFulfilled(this.value);
                    // x可能是一个proimise
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    //Promise/A+ 2.2.7.2
                    reject(e)
                }
                }, 0);
            }


            // if (this.status === Rejected) {
            //     setTimeout(() => {
            //         try {
                    
            //             const data = onRejeced(this.reason);
            //             resolvePromise(promise2, data, resolve, reject);
                    
            //         } catch(e) {
            //             reject(e);
            //         }
            //     },0);
                
            // }
             if (this.status === Rejected) {
                //Promise/A+ 2.2.3
                setTimeout(() => {
                try {
                    let x = onRejected(this.reason);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e)
                }
                }, 0);
            }
            // if (this.status === Pending) {
            //     this.resolveList.push(() => {
            //         setTimeout(() => {
            //             try {                     
            //                 const data = onFulfilled(this.value);
            //                 console.log('pending', data);
            //                 resolvePromise(promise2, data, resolve, reject);
            //             } catch(e) {
            //                 reject(e);
            //             }
            //         }, 0);
            //     });
            //     this.rejectList.push(() => {
            //         setTimeout(() => {
            //             try {                       
            //                 const data = onRejeced(this.reason);
            //                 resolvePromise(promise2, data, resolve, reject);                       
            //             } catch(e) {
            //                 reject(e);
            //             }
            //         }, 0);
            //     });
            // }
            if (this.status === Pending) {
                this.resolveList.push(() => {
                setTimeout(() => {
                    try {
                    let x = onFulfilled(this.value);
                    resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                    reject(e)
                    }
                }, 0);
                });

                this.rejectList.push(()=> {
                setTimeout(() => {
                    try {
                    let x = onRejected(this.reason);
                    resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                    reject(e)
                    }
                }, 0);
                });
            }
        })
        return promise2;
        
    }

}

Promise.all = function(arr) {
    if (!Array.isArray(arr)) {
        const type = typeof arr;
        throw new Error(`${type} ${arr} is not iterable`)
    }
    return new Promise((resolve, reject) => {
        let res = [];
        let orderIndex = 0;
        const processTick = function (item, index) {
            res[index] = item;
            if (++orderIndex === arr.length) {
                resolve(res);
            }
        }

        for(let i = 0; i < arr.length; i++) {
            const item = arr[i];
            if (item && typeof item.then === 'function') {
                item().then((value) => {
                    processTick(value, i);
                }, reject)
            } else {
                processTick(item, i);
            }
        }
    })
}

Promise.race = function(arr) {
    if (!Array.isArray(arr)) {
        const type = typeof arr;
        throw new Error(`${type} ${arr} is not iterable`)
    }

    return new Promise((resolve, reject) => {
        for (let i = 0; i < arr.length; i++) {
            const item = arr[i];
            if (item && typeof item.then === 'function') {
                item().then(resolve, reject);
            } else {
                resovle(item);
            }
        }
    })
}

Promise.allSettled = function (arr) {
    if (!Array.isArray(arr)) {
        const type = typeof arr;
        throw new Error(`${type} ${arr} is not iterable`)
    }

    return new Promise(resolve => {
        let res = [];
        let orderIndex = 0;
        let length = arr.length;
        const processTick = (item, index) => {
            res[index] = item;

            if (++orderIndex === length) {
                resolve(res);
            }

            
        }

        for (let i = 0; i < length; ++i) {
            const item = arr[i];
            if (item && typeof item.then === 'function') {
                item().then((value) => {
                    processTick({
                        value,
                        status: 'fufilled'
                    }, i)
                }, err => {
                    processTick({
                        err,
                        status: 'rejected'
                    }, i);
                })
            } else {
                processTick({
                        value: item,
                        status: 'fufilled'
                    }, i)
            }
        }
    })
}

// let p = new Promise((res, rej) => {
//     console.log('开始异步');
//     // res('执行resolve');
//     setTimeout(() => {
//         console.log('执行resolve');
//         res('执行resolve');
//     }, 1000);
// });
// p.then(val => {
//     console.log('成功', val);
// }, res => {
//     console.log('失败', res);
// }).then(val => {
//     console.log('再次成功');
// });

const promise = new Promise((resolve, reject) => {
    console.log('开始执行');
    setTimeout(() => {
        // reject('失败');
        resolve('成功')
    }, 1000);
  
}).then().then().then(data=>{
  console.log('success', data);
},err=>{
  console.log('err',err);
})


console 命令行工具 X clear

                    
>
console