Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reselect与memoize-one主要源码解析 #66

Open
jyzwf opened this issue Feb 18, 2019 · 0 comments
Open

reselect与memoize-one主要源码解析 #66

jyzwf opened this issue Feb 18, 2019 · 0 comments

Comments

@jyzwf
Copy link
Owner

jyzwf commented Feb 18, 2019

reselect

reselect使用的缓存主要是利用闭包,将上一次传入函数的参数与这次调用时传入的参数进行比较(浅比较),如果发生了改变就执行结果函数,然后利用闭包记录该次传入的参数与函数执行结果值:

export function defaultMemoize(func, equalityCheck = defaultEqualityCheck) {
  let lastArgs = null
  let lastResult = null
  // we reference arguments instead of spreading them for performance reasons
  return function () {
    if (!areArgumentsShallowlyEqual(equalityCheck, lastArgs, arguments)) {
      // apply arguments instead of spreading for performance.
      lastResult = func.apply(null, arguments)
    }

    lastArgs = arguments
    return lastResult
  }
}

同时在该包里面使用了两次该缓存函数:

  1. 当调用函数时,缓存传入的参数
  2. 缓存各个依赖的执行结果

核心代码结果如下:
image

memoize-one

该库原理与reselect基本一致,也是利用了闭包,不同的是他除了判断传入参数不一样外,还判断了函数执行时,上下文(this)的不同,同时它还强调了结果函数抛出异常的情况,核心代码如下:

export default function<ResultFn: (...Array<any>) => mixed>(
  resultFn: ResultFn,
  isEqual?: EqualityFn = simpleIsEqual,
): ResultFn {
  let lastThis: mixed;
  let lastArgs: Array<mixed> = [];
  let lastResult: mixed;
  let calledOnce: boolean = false;	// 必须执行一次,防止出现 memoized.call(undefined)的情况,详见下面例子

  const result = function(...newArgs: Array<mixed>) {
    if (calledOnce && lastThis === this && isEqual(newArgs, lastArgs)) {
      return lastResult;
    }
		
    // 当这里抛出异常时,就不再重写响应的变量,从而保证了下一次如果函数执行时如果和报错前的参数一样,
    // 可以利用缓存,以及如果上一次函数执行报错了,再次执行该函数时,重新调用结果函数
    lastResult = resultFn.apply(this, newArgs);
    calledOnce = true;
    lastThis = this;
    lastArgs = newArgs;
    return lastResult;
  };
  return (result: any);
}
import memoizeOne from 'memoize-one';

const canThrow = name => {
    console.log('called');
    if (name === 'throw') {
        throw new Error(name);
    }
    return { name };
};

const memoized = memoizeOne(canThrow);

console.log(memoized.call(undefined));
console.log(memoized.call(undefined));
@jyzwf jyzwf changed the title reselect主要源码解析 reSelect主要源码解析 Feb 18, 2019
@jyzwf jyzwf changed the title reSelect主要源码解析 reselect主要源码解析 Feb 18, 2019
@jyzwf jyzwf changed the title reselect主要源码解析 reselect与memoize-one主要源码解析 Feb 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant