你與弄懂promise之間可能只差這篇文章(二)

點我看看~es6

前言:可能存在闡述不許確之處,歡迎指正~promise

Promise在long time ago就活躍於Javascript社區,受到開發者歡迎,只不過到近幾年才被歸入ECMA規範。異步

咱們爲何要使用Promsie?this

由於:code

咱們不但願,過了幾個月以後,代碼只有上帝纔看得懂;
咱們不但願,回調代碼越寫越往右,只能換更大的顯示器看;
咱們但願,哪怕過了好久,代碼依舊邏輯清晰,看懂不費吹灰之力;
咱們但願,可以用本身的雙手,控制住異步流的動向,就像同步代碼同樣;
有逼格...
(歡迎補充)ip

話很少說,上源碼(採用es6/es7, 建立一個Commitment類模仿Promise)::開發

class Commitment {
    constructor (executor) {
        this.status = "pending";
        this.value = void(0);
        this.reason = void(0);
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];
        
        const resolve = (value) => {
            if (value instanceof Promise) {
                return value.then(resolve, reject)
            }
            
            setTimeout(() => {
                if (this.status === "pending") {
                    this.status = "resolved";
                    this.value = value;
                    this.onResolvedCallbacks.forEach(cb => cb(value));
                }
            })
            
        }
        const reject = (reason) => {
            setTimeout(() => {
                if (this.status === "pending") {
                    this.status = "rejected";
                    this.reason = reason;
                    this.onRejectedCallbacks.forEach(cb => cb(reason));
                } 
            })
        }
        
        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }
    then (onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value;
        onRejected = typeof onRejected === "function" ? onRejected : reason => {
            throw reason
        };
        const resolveCommitment = (Commitment2, x, resolve, reject) => {
            if (Commitment2 === x) {
                return reject(new TypeError("A promise cannot be resolved with itself"))
            }
            let then, called;
            if (x !== null && (typeof x === "object" || typeof x === "function")) {
                try {
                    then = x.then;
                    if (typeof then === "function") {
                        then.call(x, y => {
                            if (called) return
                            called = true;
                            resolveCommitment(Commitment2, y, resolve, reject);
                        }, r => {
                            if (called) return
                            called = true;
                            reject(r)
                        })
                    } else {
                        resolve(x)
                    }
                } catch (e) {
                    if (called) return
                    called = true;
                    reject(e)
                }
            } else {
                resolve(x)
            }
        }
        let Commitment2, x;
        if (this.status === "resolved") {
            Commitment2 = new Commitment((resolve, reject) => {
                setTimeout(() => {
                    try {
                        x = onFulfilled(this.value);
                        resolveCommitment(Commitment2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    } 
                });
            })
            
        }
        if (this.status === "rejected") {
            Commitment2 = new Commitment((resolve, reject) => {
                setTimeout(() => {
                    try {
                        x = onRejected(this.reason);
                        resolveCommitment(Commitment2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                })
            })
        }
        if (this.status === "pending") {
            Commitment2 = new Commitment((resolve, reject) => {
                this.onResolvedCallbacks.push((value)=> {
                    try {
                        x = onFulfilled(value);
                        resolveCommitment(Commitment2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    } 
                })
                this.onRejectedCallbacks.push((reason) => {
                    try {
                        x = onRejected(reason);
                        resolveCommitment(Commitment2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                })
            })
        }
        
        return Commitment2
    }
}
相關文章
相關標籤/搜索