提问人:Nitor 提问时间:7/26/2023 最后编辑:Nitor 更新时间:7/26/2023 访问量:72
等待 promise 解析到与其无关的回调
Wait for promise to resolve in not related to it callback
问:
我正在开发一个 Steam 机器人(但问题只是关于 JS)。我有以下代码:
const steam = new SteamUser(); // from steam-user library
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function steamAddFriend(user_steam_id) {
// 3 attempts
for (let i = 0; i < 3; i++) {
try {
await steam.addFriend(user_steam_id);
console.log('Friend request is sent');
// everything is ok
} catch (err) {
if (err.eresult === SteamUser.EResult.DuplicateName) {
if (steam.myFriends[user_steam_id] === SteamUser.EFriendRelationship.Friend) {
console.log('This user is already in the friends list');
} else if (steam.myFriends[user_steam_id] === SteamUser.EFriendRelationship.RequestInitiator) {
console.log('The friend request has already been sent earlier');
}
// non-critical error, but there is no point to continue trying
} else if ((err.eresult === SteamUser.EResult.ServiceUnavailable || err.message === 'Request timed out') && i < 2) {
// problem with Steam servers, wait 10 seconds and try again
await sleep(10000);
continue;
} else {
// critical error. for example, user_steam_id is invalid
// sendNotification is fetch based function to send notification to me
await sendNotification();
}
}
break; // break the loop if there is no need to continue trying
}
try {
// fetch based function to send updates to backend
await sendUpdate1(user_steam_id);
} catch (err) {
// handle error
}
}
// fired when relationship with user is changed (for example, a user accepted a friend request)
steam.on('friendRelationship', async (sid, relationship) => {
if (relationship === SteamUser.EFriendRelationship.Friend) {
const user_steam_id = sid.getSteamID64();
console.log('User is added to friends');
// here I need to wait until sendUpdate1 resolves
// sendUpdate2 is fetch based function to send updates to backend
await sendUpdate2(user_steam_id);
}
});
steamAddFriend('71111111111111111');
我需要回调以等待承诺解决,然后再调用。我该怎么做?请记住,机器人可以同时与多个用户一起工作。friendRelationship
sendUpdate1
sendUpdate2
答:
0赞
Stichiboi
7/26/2023
#1
我不确定您为什么要在事件处理程序中等待。如果这不是等待的要求,我会这样写:friendRelationship
// fired when relationship with user is changed (for example, a user accepted a friend request)
steam.on('friendRelationship', (sid, relationship) => {
if (relationship === SteamUser.EFriendRelationship.Friend) {
const user_steam_id = sid.getSteamID64();
console.log('User is added to friends');
sendUpdate1(user_steam_id).then(() => sendUpdate2(user_steam_id));
}
});
的处理程序立即完成,但将执行异步,一旦完成,执行 ,也是异步的。steam.on
sendUpdate1
sendUpdate2
评论
0赞
Nitor
7/26/2023
sendUpdate1
需要在发送好友请求后立即调用(即 已解决)。 在接受好友请求时触发(只应在此之后调用)。steam.addFriend
friendRelationship
sendUpdate2
2赞
Bergi
7/26/2023
#2
听起来您想将返回的 promise 存储在按用户 ID 键控的查找映射中:steamAddFriend
const openFriendRequests = new Map();
steam.on('friendRelationship', async (sid, relationship) => {
if (relationship === SteamUser.EFriendRelationship.Friend) {
const userSteamId = sid.getSteamID64();
console.log(`User is added to friends of ${userSteamId}`);
const request = openFriendRequests.get(userSteamId);
if (request) {
openFriendRequests.delete(userSteamId);
await request; // wait until sendUpdate1 resolves
await sendUpdate2(userSteamId);
} else {
console.log('not a response to a friend request created by this code');
}
}
});
openFriendRequest.set('71111111111111111', steamAddFriend('71111111111111111'));
评论
0赞
Nitor
7/26/2023
好主意,但用户可能不接受好友请求或长时间后接受。存储 promise 可能会导致内存泄漏。
0赞
Bergi
7/26/2023
如果有很多打开的好友请求,内存可能会增长,但如果所有请求最终都被接受,内存就不会泄漏。我们在这里谈论的是多少用户?我只是隐含地假设您正在为多个不同的用户 ID 运行此代码。请求还会发生什么,当它们被拒绝时,你是否也会收到一个事件?
1赞
Bergi
7/26/2023
或者,您可以存储具有活动 update1 请求的好友请求映射,即 .然后,在处理程序中,仅当 promise 仍然存在时,您才等待它,并始终调用 .activeFriendRequests.set(id, steamAddFriend(id).finally(() => { activeFriendRequests.delete(id); }))
on('friendRelationship')
request
sendUpdate2
0赞
Bergi
7/26/2023
无论哪种方式,您都必须决定如何处理不是由程序操作引起的事件。你还想吗?你想忽略它们吗?您是否需要区分程序的多个单独运行(或者:如何处理服务器的重新启动)?如果这些东西很重要,你将需要某种持久性层。friendRelationship
sendUpdate2
0赞
Nitor
7/26/2023
是,当用户拒绝请求时触发。但不能保证所有请求最终都会被接受,毕竟我与真实用户打交道。我使用具有少量 RAM 的廉价 VPS,不想将其浪费在存储待处理的请求上。所有内容都存储在数据库中,事件由后端验证。您的替代建议似乎很合适。friendRelationship
friendRelationship
评论
steam
user_steam_id
steamAddFriend
steamAddFriend(steam, '71111111111111111')
'friendRelationship'
sendUpdate2
)被破坏。- 实际上,正确的解决方案是放弃此要求。让您的后端以任何顺序接受请求。如果出于某种原因确实存在硬性要求,请检查它并在后端(而不是在客户端代码中)强制执行它。