I have this sort of lazy initialization code in my program:
let user = null;
let getUser = async () => {
if(!user) {
user = await getUserSomehow();
}
return user;
};
I understand that it is not safe, due to a possible race condition if I have the next code:
// one place of the program
let u1 = await getUser();
...
// another place of the program running during getUserSomehow() for u1 still hasn't finished
let u2 = await getUser();
getUserSomehow()
will be called two times instead of one.
How to avoid this situation?
I have this sort of lazy initialization code in my program:
let user = null;
let getUser = async () => {
if(!user) {
user = await getUserSomehow();
}
return user;
};
I understand that it is not safe, due to a possible race condition if I have the next code:
// one place of the program
let u1 = await getUser();
...
// another place of the program running during getUserSomehow() for u1 still hasn't finished
let u2 = await getUser();
getUserSomehow()
will be called two times instead of one.
How to avoid this situation?
Share Improve this question edited Nov 11, 2019 at 9:44 Arsenii Fomin asked Nov 11, 2019 at 6:10 Arsenii FominArsenii Fomin 3,3564 gold badges25 silver badges48 bronze badges 2-
1
Just drop the
await
. – Bergi Commented Nov 11, 2019 at 7:43 - @Bergi your ment is so short that at first glance it looks stupid (like you are advising to get rid of async code). However, if it's not planned to use "user" variable directly anywhere, you are pletely right. – Arsenii Fomin Commented Nov 11, 2019 at 9:47
1 Answer
Reset to default 10When 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 pletion 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.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744135492a4560039.html
评论列表(0条)