When called for the first time, assign a Promise instead, and on further calls, return that Promise:
let userProm = null;
let getUser = () => {
if (!userProm) {
userProm = getUserSomehow();
}
return userProm;
};
Even better, scope userProm
only inside getUser
, to be safer and clear:
const getUser = (() => {
let userProm = null;
return () => {
if (!userProm) {
userProm = getUserSomehow();
}
return userProm;
};
})();
const getUserSomehow = () => {
console.log('getting user');
return Promise.resolve('data');
};
const getUser = (() => {
let userProm = null;
return () => {
if (!userProm) {
userProm = getUserSomehow();
}
return userProm;
};
})();
(async () => {
const userProm1 = getUser();
const userProm2 = getUser();
Promise.all([userProm1, userProm2]).then(() => {
console.log('All done');
});
})();
Your existing code happens to be safe, because the assignment to user
will occur before the first call of getUser
finishes:
const getUserSomehow = () => {
console.log('Getting user');
return Promise.resolve('data');
};
let user = null;
let getUser = async() => {
if (!user) {
user = await getUserSomehow();
}
return user;
};
(async () => {
let u1 = await getUser();
let u2 = await getUser();
console.log('Done');
})();
But it wouldn't be if the Promises were initialized in parallel, before one of them was await
ed to completion first:
const getUserSomehow = () => {
console.log('Getting user');
return Promise.resolve('data');
};
let user = null;
let getUser = async() => {
if (!user) {
user = await getUserSomehow();
}
return user;
};
(async() => {
let u1Prom = getUser();
let u2Prom = getUser();
await Promise.all([u1Prom, u2Prom]);
console.log('Done');
})();
As shown above, assigning the Promise to the persistent variable (instead of await
ing the value inside getUser
) fixes this.