Last active
April 14, 2020 20:19
-
-
Save AndreiCalazans/ef0e4f2461855d42ec92a1db5913a831 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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; |
Use this for shallow equal
var keyList = Object.keys;
exports.equal = 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 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;
The last update is in regards to toString. It is not performant enough, the downside to not stringifying the function signatures is anonymous and arrow functions with the exact same signature will be duplicated. To mitigate this the client should always prefer shared named function definitions to get the most out of our client cache.
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
reduxjs/reselect#401