Skip to content

Instantly share code, notes, and snippets.

@aneurysmjs
Last active October 8, 2019 12:55
Show Gist options
  • Save aneurysmjs/70d032666d0ffba22000faed34c9bf1c to your computer and use it in GitHub Desktop.
Save aneurysmjs/70d032666d0ffba22000faed34c9bf1c to your computer and use it in GitHub Desktop.
benchmarking each type of reducer
const { PerformanceObserver, performance } = require('perf_hooks');
const obs = new PerformanceObserver((items) => {
console.log(items.getEntries()[0]);
performance.clearMarks();
});
obs.observe({ entryTypes: ['measure'] });
const has = Object.prototype.hasOwnProperty;
function createReducer(initialState, handlers) {
return function reducer(state = initialState, action) {
if (has.call(handlers, action.type)) {
return handlers[action.type](state, action);
}
return state;
};
}
const initialState = {
error: null,
isLoading: false,
stuff: [],
};
function ifReducer(state, action) {
if ('REQUEST') {
return {
...state,
isLoading: true,
};
} else if ('SUCCESS') {
const {
payload: {
response: { data },
},
} = action;
return {
...state,
isLoading: false,
stuff: [...data],
};
} else if ('FAILURE') {
const {
payload: { error },
} = action;
return {
...state,
isLoading: false,
error,
};
} else {
return state;
}
}
function switchReducer(state, action) {
switch (action.type) {
case 'REQUEST':
return {
...state,
isLoading: true,
};
case 'SUCCESS':
const {
payload: {
response: { data },
},
} = action;
return {
...state,
isLoading: false,
stuff: [...data],
};
case 'FAILURE':
const {
payload: { error },
} = action;
return {
...state,
isLoading: false,
error,
};
default:
return state;
}
}
const objectReducer = createReducer(initialState, {
['REQUEST'](state) {
return {
...state,
isLoading: true,
};
},
['SUCCESS'](state, action) {
const {
payload: {
response: { data },
},
} = action;
return {
...state,
isLoading: false,
stuff: [...data],
};
},
['FAILURE'](state, action) {
const {
payload: { error },
} = action;
return {
...state,
isLoading: false,
error,
};
},
});
function switchReducer(state, action) {
switch (action.type) {
case 'REQUEST':
return {
...state,
isLoading: true,
};
case 'SUCCESS':
const {
payload: {
response: { data },
},
} = action;
return {
...state,
isLoading: false,
stuff: [...data],
};
case 'FAILURE':
const {
payload: { error },
} = action;
return {
...state,
isLoading: false,
error,
};
default:
return state;
}
}
const map = new Map();
function mapReducer(state, action) {
/** this way is much more slower since it 'recreates' the Map on each call, so is a shit */
// const map = new Map([
// [
// 'REQUEST',
// {
// ...state,
// isLoading: true,
// }
// ],
// [
// 'SUCCESS',
// (() => {
// const {
// payload: {
// response: { data },
// },
// } = action;
// return {
// ...state,
// isLoading: false,
// stuff: [...data],
// }
// })()
// ],
// [
// 'FAILURE',
// (() => {
// const {
// payload: { error },
// } = action;
// return {
// ...state,
// isLoading: false,
// error,
// };
// })()
// ]
// ]);
map
.set('REQUEST', {
...state,
isLoading: true
})
.set(
'SUCCESS',
(() => {
const {
payload: {
response: { data }
}
} = action;
return {
...state,
isLoading: false,
stuff: [...data]
};
})()
)
.set(
'FAILURE',
(() => {
const {
payload: { error }
} = action;
return {
...state,
isLoading: false,
error
};
})()
);
return map.get(action.type) || state;
}
const actionRequest = {
type: 'REQUEST',
/** is only needed when running through the mapReducer since it runs every case no matter what, so is a shit */
payload: {
response: {
data: [{ name: 'Macbook Pro' }]
}
}
};
const actionSuccess = {
type: 'SUCCESS',
payload: {
response: {
data: [{ name: 'Macbook Pro' }]
}
}
};
const actionError = {
type: 'FAILURE',
payload: {
response: {
error: { message: 'fuck you' }
}
}
};
const actions = [actionRequest, actionSuccess, actionError];
let iterations = 1e6;
performance.mark('start');
/**
* @desc uncomment the reducer to test
*/
while(iterations--) {
actions.forEach(a => ifReducer({}, a));
// actions.forEach(a => switchReducer({}, a));
// actions.forEach(a => objectReducer({}, a));
// actions.forEach(a => mapReducer({}, a));
}
performance.mark('end');
performance.measure('if vs switch vs object vs map', 'start', 'end');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment