面试:promise、createstore、发布订阅代码实现

576 阅读2分钟

1、promise

            constructor(excutor) {
                                                   // this--> 当前promise的实例;
                this.state = "pending";            // 创建实例,默认状态是pending;
                this.fulfilledEvent = [];          // 当前实例成功的事件池;
                this.rejectedEvent = [];           // 当前实例失败的事件池;
                let resolve = (result) => {       // 只有调用resolve时,该实例的状态要改变为成功态;
                    if (this.state !== "pending") return;    // 如果不是pending;不需要往下执行
                    this.state = "fulfilled";                // 循环成功态的事件池;依次执行;
                    clearTimeout(this.timer);
                    this.timer = setTimeout(() => {
                        this.fulfilledEvent.forEach((item) => {
                            if (typeof item === "function") {
                                item(result);
                            }
                        })
                    }, 0)
                }
                let reject = (result) => {       // 只有调用resolve时,该实例的状态要改变为失败态;
                    if (this.state !== "pending") return;
                    this.state = "rejected";  // 执行之前,首先清除之前的定时器;为了防止定时器的累加;
                    clearTimeout(this.timer);
                    this.timer = setTimeout(() => {
                        this.fulfilledEvent.forEach((item) => {
                            if (typeof item === "function") {
                                item(result);
                            }
                        })
                    }, 0)
                }
                try {                        // 一旦执行报错,那么会执行reject;
                    excutor(resolve, reject)
                } catch (e) {
                    reject(e);
                }
            }
            then(resolveFn, rejectFn) {             // then 放到了MyPromise 的原型上
                                  // 实现then的链式写法,需要then返回一个promise的实例;
                return new MyPromise((resolve, reject) => {
                    this.fulfilledEvent.push(() => {
                        let x = resolveFn();
                        x instanceof MyPromise ? x.then(resolve, reject) : resolve();
                    });
                    this.rejectedEvent.push(rejectFn);
                })
            }
        }

2、createstore

function createStore(reducer){                        //是一个函数
        let state;                                    //createStore的state定义,不赋值
        let getState=()=>JSON.parse(JSON.stringify(state));    //深克隆
        let listeners=[];                              //listeners是一个事件池,存储订阅的方法
        function dispatch(action){        //1、通过动作修改当前仓库中的state  2、可以让订阅的方法执行
            state=reducer(state,action);
            listeners.forEach((item,index)=>{
                if(typeof item==='function'){           //reducer第一次执行是undefined
                    item();
                }
            })
        }
        dispatch({});    //初始化state,在createStore中有个订阅的方法,当外界调用dispatch之后,会立即执行订阅的函数
        let subscribe=(fn)=>{            //subscribe返回一个取消订阅的方法
            listeners.push(fn);
            return ()=>{            //返回一个取消订阅的方法,当返回值执行时,取消订阅
                listeners=listeners.filter((item,index)=>item!==fn)
            }
        }
        return {
            getState,
            dispatch,
            subscribe
        }
    }
    export default createStore;

3、发布订阅

let obj = {};
    //订阅
    function on(obj, type, fn) {
        if (!obj[type]) {
            obj[type] = [];
        }
        let ary = obj[type];
        for (let i = 0; i < ary.length; i++) {
            if (ary[i] === fn) {
                return;
            }
        }
        ary.push(fn);
    }
    //发布
    function emit(obj, type) {
        let a = obj[type];
        if (a) {
            for (let i = 0; i < a.length; i++) {
                if (typeof a[i] === 'function') {
                    a[i].call(obj);
                }
            }
        }
    }
    //取消
    function off(obj, type, fn) {
        let ary = obj[type];
        for (let i = 0; i < ary.length; i++) {
            if (fn === ary[i]) {
                ary[i] = null;
                return;
            }
        }
    }
    on(obj, 'b', fn1);