Skip to content

Instantly share code, notes, and snippets.

@AndreiCalazans
Last active April 14, 2020 20:19
Show Gist options
  • Save AndreiCalazans/ef0e4f2461855d42ec92a1db5913a831 to your computer and use it in GitHub Desktop.
Save AndreiCalazans/ef0e4f2461855d42ec92a1db5913a831 to your computer and use it in GitHub Desktop.
'use strict';
var keyList = Object.keys;
function equal(a, b) {
if (a === b) return true;
if (!(a instanceof Object) || !(b instanceof Object)) return false;
var keys = keyList(a);
var length = keys.length;
for (var i = 0; i < length; i++)
if (!(keys[i] in b)) return false;
for (var i = 0; i < length; i++)
if (a[keys[i]] !== b[keys[i]]) return false;
return length === keyList(b).length;
};
const ResultMap = new Map();
const DepMap = new Map();
/*
Use this to garbage collect every 30 seconds.
function garbageCollect() {
ResultMap.clear();
DepMap.clear();
}
setInterval(garbageCollect, 30000);
*/
function garbageCollect() {
ResultMap.clear();
DepMap.clear();
}
setInterval(garbageCollect, 30000);
function createSelector(deps, mapResult) {
return function mapStateToPropsSelector(state, props) {
let isDirty = false;
function selectState(depFn) {
const returnValue = depFn(state, props);
const CurrentState = !DepMap.has(depFn) ? "INITIAL" : "UPDATE";
switch (CurrentState) {
case "INITIAL": {
DepMap.set(depFn, returnValue);
isDirty = true;
return returnValue;
}
case "UPDATE": {
if (!DepMap.get(depFn) || !equal(DepMap.get(depFn), returnValue)) {
DepMap.set(depFn, returnValue);
isDirty = true;
}
return returnValue;
}
}
}
let depsToUse = deps;
if (!Array.isArray(deps)) {
depsToUse = [deps];
}
const depsArray = depsToUse.map(selectState);
let result;
if (isDirty || !ResultMap.has(mapResult) || !equal(ResultMap.get(mapResult)[1], depsArray)) {
result = mapResult.apply({}, depsArray); // this computes again
ResultMap.set(mapResult, [result, depsArray]);
}
return result || ResultMap.get(mapResult)[0];
};
}
exports.createSelector = createSelector;
@AndreiCalazans
Copy link
Author

Here is another version: We need to test to see which is faster.


'use strict';

var keyList = Object.keys;

function equal(a, b) {
  if (a === b) return true;
  if (!(a instanceof Object) || !(b instanceof Object)) return false;

  var keys = keyList(a);
  var length = keys.length;

  for (var i = 0; i < length; i++)
    if (!(keys[i] in b)) return false;

  for (var i = 0; i < length; i++)
    if (a[keys[i]] !== b[keys[i]]) return false;

  return length === keyList(b).length;
};

/*
Use this to garbage collect every 30 seconds.
function garbageCollect() {
  ResultMap.clear();
  DepMap.clear();
}
setInterval(garbageCollect, 30000);
*/

// function garbageCollect() {
//   ResultMap.clear();
//   DepMap.clear();
// }

// setInterval(garbageCollect, 30000);

let counter = 0;
let ResponseCache = new Map();
function createSelector(deps, mapResult) {
  let uniqueKey = ++counter;
  ResponseCache.set(uniqueKey, [undefined, undefined]);

  // cachedResponse[uniqueKey]
  // This way you can store the depsArray used by A unique key.
  return function mapStateToPropsSelector(state, props) {
    let depsToUse = deps;
    if (!Array.isArray(deps)) {
      depsToUse = [deps];
    }

    let shouldRecompute = false;
    let depsArray = [];
    // let currentIndex = 0;
    for (let dep of depsToUse) {
      const selectedResult = dep(state, props);
      depsArray.push(selectedResult);
    }
    const currentCache = ResponseCache.get(uniqueKey);

    if (!currentCache[0] || !currentCache[1] || !equal(depsArray, currentCache[1])) {
        ResponseCache.set(uniqueKey, [mapResult.apply({}, depsArray), depsArray]);
    }
    return ResponseCache.get(uniqueKey)[0];
  };
}

exports.createSelector = createSelector;


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment