Search code examples
javascriptasync-awaitpromisecallbackevent-handling

Wait for promise to resolve in not related to it callback


I am developing a Steam bot (but the question is only about JS). I have the following code:

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');

I need friendRelationship callback to wait for the sendUpdate1 promise to resolve before calling sendUpdate2. How can I do this? Keep in mind that the bot can work with several users at the same time.


Solution

  • Sounds like you want to store the promise returned by steamAddFriend in a lookup map keyed by user id:

    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'));