实现effect的scheduler功能

64 阅读1分钟

scheduler: 调用effect传第一个参数fn,第二个参数带scheduler的function时,则第一次执行effect时,直接执行fn,当响应式对象改变时,不会执行fn,而是执行scheduler,如果说当执行runner的时候会再次执行fn 单元测试:

it('scheduler', () => {
  let dummy;
  let run:any;
  const scheduler = jest.fn(() => {
    run = runner;
  });
  const obj = reactive({foo: 1});
  const runner = effect(
    () => {
      dummy = obj.foo;
     },
    { scheduler}
   );
   // 第一次执行时执行fn
   expect(scheduler).not.toHaveBeenCalledTimes(1);
   expect(dummy).toBe(1);
   // update
   obj.foo++;
   expect(scheduler).toHaveBeenCalledTimes(1);
   expect(dummy).toBe(1);
   // 再次执行fn
   run();
   expect(dummy).toBe(2);

scheduler源码实现:

  let activeEffect;
  class ReactiveEffect{
    private _fn:any;
    constructor(fn, public scheduler?){
      this._fn = fn;
      
    }
    function run(){
      activeEffect = this;
      this._fn();
      return this._fn;
    }
  }
  
  export function trigger(target, key){
    let depsMap = targetMap.get(target);
    let dep = depsMap.get(key);
    for(const effect of dep){
      // 修改 先去判断是否有scheduler
      if(effect.scheduler){
        effect.scheduler();
      } else {
        effect.run();
      }
    }
  }
  export function effect(fn, options={}){
    const _effect = new ReactiveEffect(fn, options.scheduler);
    _effect.run();
    const runner = _effect.run.bind(_effect);
    return runner;