实现effect的scheduler功能

75 阅读1分钟

scheduler的实现

scheduler是effect函数的第二个参数,schedule是一个函数

在测试中书写最核心的代码流程

it("scheduler",()=>{
        //1.通过effect的第二个参数给定的scheduler的一个函数
        //2.当effect第一次执行时还会执行effect的第一个参数(回调函数)
        //3.当响应式对象触发set 值更新时,不会执行fn,而是执行scheduler
        //4.如果说执行runner的时候,会再次执行fn(effect的第一个参数)
        let dummy;
        let run:any;
        //scheduler接收一个函数
        const scheduler=jest.fn(()=>{
            run=runner;
        });
        const obj=reactive({foo:1});
        const runner=effect(
            ()=>{
                dummy=obj.foo;
            },
            {scheduler}
        );
        //断言scheduler一开始不会被调用
        expect(scheduler).not.toHaveBeenCalled();
        //判断dummy值是否为1,如果为1,说明effect的第一个函数会执行 第二个函数不会执行
        expect(dummy).toBe(1);
        //should be called on first trigger
        //当响应式对象的值发生改变
        obj.foo++;
        //当响应式对象的值发生改变,会调用scheduler,而不会再次执行()=>{dummy=obj.foo;},
        expect(scheduler).toHaveBeenCalledTimes(1);
        //should not run yet
        //dummy值仍然为1,说明没有执行()=>{dummy=obj.foo;},
        expect(dummy).toBe(1);
        //manually run
        run();
        //should have run
        expect(dummy).toBe(2);
    });

那么具体如何实现呢?

首先要在effect函数中接收第二个参数options,在effect里面获取到scheduler

image.png 然后scheduler一开始不会被调用,当响应式对象的值发生改变,会调用scheduler,而不会再次执行()=>{dummy=obj.foo;},由于当响应式对象的值发生改变会触发trigger函数,trigger里面会调用run方法来执行收集的依赖,即运行effect的第一个函数,因此可以在这里判断一下

image.png

如何把scheduler传进去

image.png

image.png

scheduler功能完成,完整代码见下篇文章