手动实现promise

63 阅读1分钟

class MyPromise {

    constructor(fn) {
        try {
            fn((res) => this.resolve(res), (err) => this.reject(err))
        } catch (error) {
            this.reject(error)
        }
    }
    "[[PromiseState]]" = 'pending';
    resolve(res) {
        this["[[PromiseState]]"] = 'fulfilled'
        this.run(() => this.each(res, this._thenList))
    };
    reject(err) {
        this["[[PromiseState]]"] = 'rejected'
        this.run(() => this.each(err, this._catchList))
    };
    run(fn) {
        if (typeof MutationObserver !== 'undefined') {
            let dom = document.createElement('div')
            const ob = new MutationObserver(() => {
                ob.disconnect();
                fn();
                dom = undefined;
            })
            ob.observe(dom, { attributes: true })
            dom.setAttribute('a', 2)
        } else if (typeof process !== 'undefined') {
            process.nextTick(fn);
        } else {
            setTimeout(fn)
        }
        
    }
    each(_res, list) {
        let res = _res;
        let fn = list.shift();
        const walk = () => {
            if (!fn) return;
            this.checkRes(fn(res), newRes => {
                res = newRes;
                fn = list.shift();
                walk();
            })
        }
        walk()
    }
    checkRes(res, callback) {
        if (res?.then) {
            res.then(_res => {
                callback(_res)
            })
        } else {
            callback(res);
        }
    }
    _thenList = [];
    then(fn) {
        this._thenList.push(fn)
        return this;
    }
    _catchList = [];
    catch(fn) {
        this._catchList.push(fn)
        return this;
    }

}

const myPromise = new MyPromise((resolve, reject) => {
    resolve(1)

});
setTimeout(() => console.log('setTimeout'))
myPromise.then(res => res + 44).then(res => {
    console.log(res);
}).catch(err => {
    console.log('err', err);
})