Monday 27 April 2020

Node.js singleton patterns

I'm having a debate with a colleague about good patterns for singletons in NodeJS.Currently I have a module that looks like this:async function doSomethingExpensive() { // do expensive async thing (DB calls, etc) return result; } export const SOMETHING_EXPENSIVE = doSomethingExpensive(); This results in the desired behaviour (which is doing the expensive thing once), so long as you wait on the constant elsewhere in the code (await SOMETHING_EXPENSIVE). Which looks a bit weird.Is there a nicer way to do this that lets us await on a function and is understandable?One option is simply:async function doSomethingExpensive() { // do expensive async thing (DB calls, etc) return result; } const SOMETHING_EXPENSIVE = doSomethingExpensive(); export const getSomethingExpensive = async () => SOMETHING_EXPENSIVE; This is the same, but allows us to await getSomethingExpensive() which doesn't look so weird.I also pondered doing it with Promise, because in some ways that's clearer here:const SOMETHING_EXPENSIVE = new Promise((resolve, reject) => { // do expensive async thing (DB calls, etc) resolve(result); }); export const getSomethingExpensive = async () => SOMETHING_EXPENSIVE; My colleague contends the following would work, but I think this isn't guaranteed to only do the expensive thing once, because both guard conditions may be run in the event loop before the expensive operation. Is my understanding of the event loop correct?let SOMETHING_EXPENSIVE = null; export async function getSomethingExpensive() { if (SOMETHING_EXPENSIVE) return SOMETHING_EXPENSIVE; // do expensive async thing (DB calls, etc) SOMETHING_EXPENSIVE = result; return SOMETHING_EXPENSIVE; } I think the above won't work correctly (although might do in practice 99% of the time).Thoughts?

Submitted April 27, 2020 at 01:31PM by ianjm

No comments:

Post a Comment