Reputation: 749
componentDidUpdate() {
if (this.state.currentDirectory === Constant.EVENT_DISCUSSION_COMMENTS) {
console.log("Did update", this.state.commentList[0].reply_by);
}
}
handleGetDiscussionComments = async (e) => {
const target = e.target;
const discussionID = target.getAttribute("data-key");
const currentDirectory = Constant.EVENT_DISCUSSION_COMMENTS;
if (discussionID !== null) {
const commentList = await CommentApi.getCommentBasedOndiscussion_id(
discussionID
);
await commentList.map(async (comment) => {
const username = await User.getUserName(comment["reply_by"]).then(
console.log("then", comment.reply_by)
);
comment["reply_by"] = username;
console.log("async", comment.reply_by);
});
console.log("before setState", commentList[0].reply_by);
this.setState({
commentList,
selectedDiscussionID: discussionID,
currentDirectory,
});
console.log("after setState");
}
};
so the problem is that even if i put await infront of commentList.map function, it will still execute the below code, how can I avoid that?
Output:
then 5f3207204450b32620449657
then 5f3207204450b32620449657
before setState 5f3207204450b32620449657
Did update 5f3207204450b32620449657
after setState
async DummyPerson
With this issues going on, I failed to show the username at the webpage, instead it shows the ObjectId.
Upvotes: 2
Views: 159
Reputation: 169032
You can refactor things to something like this.
.then()
was removed from the comment username mapping thingPromise.all()
was added there.handleGetDiscussionComments = async (e) => {
const target = e.target;
const discussionID = target.getAttribute("data-key");
const currentDirectory = Constant.EVENT_DISCUSSION_COMMENTS;
if (discussionID === null) {
return;
}
const commentList = await CommentApi.getCommentBasedOndiscussion_id(discussionID);
await Promise.all(
commentList.map(async (comment) => {
comment["reply_by"] = await User.getUserName(comment["reply_by"]);
}),
);
this.setState({
commentList,
selectedDiscussionID: discussionID,
currentDirectory,
});
console.log("after setState");
};
To elaborate on the (previously) last point I had:
A further improvement would be to gather a set of the user IDs that require username fetching, and only fetch each username once.
// Construct a set of unique user IDs
const userIdSet = new Set(commentList.map((c) => c.reply_by));
// Fetch an array of pairs [userid, username]
const userIdPairs = await Promise.all(
[...userIdSet].map(async (userId) => [
userId,
await User.getUserName(userId),
]),
);
// Create a mapping out of it
const userIdMap = Object.fromEntries(userIdPairs);
// Augment comment objects with `reply_by_name` from the map
commentList.forEach((c) => (c.reply_by_name = userIdMap[c.reply_by]));
Even better, you could probably cache the userid<->username mapping on client side, so when new comments are loaded, you'd likely already have the username loaded.
// a global variable (I know, usually not encouraged,
// but pragmatically should be fine,
// and can be refactored to something fancier later)
const knownUserNames = {};
// ...
async function handleGetDiscussionComments() {
// Construct a set of unique user IDs
const userIdSet = new Set(commentList.map((c) => c.reply_by));
// Fetch an array of pairs [userid, username] unless we already know the result
const userIdPairs = await Promise.all(
[...userIdSet].map(async (userId) => [
userId,
knownUserNames[userId] || (await User.getUserName(userId)),
]),
);
// Create a mapping out of it
const userIdMap = Object.fromEntries(userIdPairs);
// Augment comment objects with `reply_by_name` from the map
commentList.forEach(
(c) => (c.reply_by_name = userIdMap[c.reply_by]),
);
// Update the global known username mapping with any new results
Object.assign(knownUserNames, userIdMap);
}
Upvotes: 1
Reputation: 1430
Given that you are using map
, you can await the array of promises that you'll get with Promise.all
on map
:
await Promise.all(commentList.map(async (comment) => {
const username = await User.getUserName(comment["reply_by"]).then(
console.log("then", comment.reply_by)
);
comment["reply_by"] = username;
console.log("async", comment.reply_by);
}));
Upvotes: 2