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: 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();
}
}
CodePudding user response:
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
}
CodePudding user response:
There is no way navigating around a promise/async...await based approach but ...
... from my above comment ...
"How about returning
instance
from theasync load
function. One also might consider turning it into a function which encapsulatesinstance
."
const load = (function () {
let instance;
return (async function load () {
if ('undefined' === typeof instance) {
instance = await (new Promise(resolve =>
setTimeout(resolve, 3000, [])
));
}
return instance;
});
}());
async function foo() {
const instance = await load();
console.log('foo ... instance ...', instance)
}
async function bar() {
const instance = await load();
console.log('bar ... instance ...', instance)
}
foo(); // 2nd
bar(); // 3rd
setTimeout(bar, 6000); // 5th
setTimeout(bar, 6000); // 6th
setTimeout(() =>
console.log('(typeof instance) ?..', (typeof instance)), 5000 // 4th
);
console.log('(typeof instance) ?..', (typeof instance)); // 1st
.as-console-wrapper { min-height: 100%!important; top: 0; }