如何让Steam Bot的friendRelationship回调等待sendUpdate1完成后调用sendUpdate2
解决Steam Bot中sendUpdate1与sendUpdate2的顺序执行问题
我正在开发基于JavaScript的Steam Bot,当前代码如下:
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回调触发(比如用户接受好友请求)时,必须等待steamAddFriend函数中的sendUpdate1 Promise解析完成后,再调用sendUpdate2,同时要保证机器人能同时处理多个用户。
实现方案
核心思路是用一个Map对象来存储每个用户对应的sendUpdate1 Promise,这样无论friendRelationship回调何时触发,都能找到并等待该用户的sendUpdate1完成后再执行sendUpdate2。具体修改如下:
- 新增全局Map跟踪每个用户的
sendUpdate1任务:
// 存储每个用户的sendUpdate1 Promise,键为steamID64,值为Promise const pendingSendUpdate1 = new Map();
- 修改
steamAddFriend函数,将sendUpdate1的Promise存入Map,并在完成后清理:
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'); } 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'); } break; // non-critical error, stop trying } else if ((err.eresult === SteamUser.EResult.ServiceUnavailable || err.message === 'Request timed out') && i < 2) { await sleep(10000); continue; } else { await sendNotification(); break; } } break; } // 创建sendUpdate1的Promise并存入Map const updatePromise = (async () => { try { await sendUpdate1(user_steam_id); } catch (err) { // 保留原错误处理逻辑 console.error(`sendUpdate1 failed for ${user_steam_id}:`, err); } })(); pendingSendUpdate1.set(user_steam_id, updatePromise); // 完成后从Map中移除,避免内存泄漏 await updatePromise; pendingSendUpdate1.delete(user_steam_id); }
- 修改
friendRelationship回调,先等待对应用户的sendUpdate1完成:
steam.on('friendRelationship', async (sid, relationship) => { if (relationship === SteamUser.EFriendRelationship.Friend) { const user_steam_id = sid.getSteamID64(); console.log('User is added to friends'); // 等待该用户的sendUpdate1完成(如果存在) const updatePromise = pendingSendUpdate1.get(user_steam_id); if (updatePromise) { await updatePromise; } // 现在执行sendUpdate2 await sendUpdate2(user_steam_id); } });
方案说明
- 多用户支持:Map的键是用户的steamID64,每个用户对应独立的Promise,完全隔离不同用户的处理流程,不会互相干扰。
- 顺序保证:无论
friendRelationship回调在sendUpdate1执行前还是执行中触发,都会等待sendUpdate1完成后再执行sendUpdate2。 - 内存管理:
sendUpdate1完成后会从Map中移除对应的Promise,避免长期占用内存。
内容的提问来源于stack exchange,提问作者Nitor
相关产品推荐
相关产品推荐

