I’ve to admin I need to read more about this topic. Anyways, here is the background:
foo
andbar
need to useinstance
, which is a result of a async callload
is checking ifinstance
isundefined
, to avoid re-loading it
Example:
let instance; // Will resolve in 5 seeconds when instance is undefined async load() { if ('undefined' !== typeof instance) { return; } instance = await new Promise(resolve => setTimeout(() => { resolve([]); }, 5000)); } async foo() { await load(); // Use instance } async bar() { await load(); // Use instance }
Timeline:
foo()
will be called after 1 seconds (say t1)bar()
will be called after 3 seconds (say t3)
Conclusions:
load()
will resolve at t6 (t1 + t5) for the first timeload()
will resolve at t8 (t3 + t5) for the second time- Any call to
load()
after t6 will return immediately (that’s what I want in the first place) - There is no way to avoid the second
load()
So to the question: is there any way to avoid the second load()
(and the second resolve of the promise)? Note that foo and bar will be invoked by a framework, so I cannot “control” their invocation.
EDIT: https://www.jonmellman.com/posts/singleton-promises this is the concept of “singleton promises” relative to @Amir question
EDIT: looking at the answer (good ones!) this is quite real code of what I’m trying to do. This works as per answer, but it’s inconvenient (need to const instance = await this.load()
):
export default class { module; async load() { if (!this.module) { this.module = import('amodule').then(({ default: Ctor }) => { return new Ctor(); }); } return this.module; } async foo() { const instance = await this.load(); } async bar({ params }) { const instance = await this.load(); } }
Advertisement
Answer
I hope I understood you correctly. You can hold the raw promise and always return it. Once it’s in resolve state it, awaiting it will return the value without re-running anything.
let promise; load() { if(!promise){ promise = new Promise(resolve => setTimeout(() => { resolve([]); }, 5000)); } return promise; // await it outside }