Search code examples
javascriptnode.jses6-promise

Is there a way to use Promise.allsettled() in a way that only does one promise at a time with a delay?


Basically, let me define a delay between resolving each promise. Is there a built in way to do this, or do I have to use some sort of loop to go over an array?

I want to have a line of code that essentially does this:

let hi = await Promise.allSettled(promiseArray, delayInMS);

I've tried putting a setTimeout function over the resolve, but it just sort of puts all of them in at once with a delay before returning:

function makeBot([_u, _p]) {
    return new Promise(
        (resolve, reject) => setTimeout(() => {
            var bot = mineflayer.createBot({
                username: _u,
                get password() { return config.cracked === true ? undefined : _p },
                get auth() { return config.cracked === true ? undefined : 'microsoft' },
                host: config.server,
                port: config.port,
                version: config.version
            });

            bot.on('error', (err) => reject(err));

            bot.once('spawn', () => {
                resolve(bot);
            });
        }, config.logininterval)
    );
};
//config.logininterval is set to number 1000

//later in the code...
function getRandomNameMap(amount) {
    let names = [];
    for (let i = 1; i <= amount; i++) {
        let generatedName = config.crackedusername;
        if (config.userandomsuffix === true) {
            generatedName = generatedName + g.getRandomWords(1, config.randomprefixlength);
        };
        names.push(generatedName);
    };
    return names;
};
const usernames = getRandomNameMap(config.crackedamount).map(login => login.split(':'));
process.stdout.write(`Creating bots: `);
const botProms = usernames.map(makeBot);
bots = (await Promise.any(botProms)).map(({ value, reason }) => value || reason).filter(value => !(value instanceof Error));

Basically, I want the bots to login one after another with a delay.


Solution

  • Ok, so I've used @jfriend00's comment to solve this. I did this:

    function makeBot([_u, _p]) {
        return new Promise(
            (resolve, reject) => {
                var bot = mineflayer.createBot({
                    username: _u,
                    get password() { return config.cracked === true ? undefined : _p },
                    get auth() { return config.cracked === true ? undefined : 'microsoft' },
                    host: config.server,
                    port: config.port,
                    version: config.version
                });
    
                bot.on('error', (err) => reject(err));
                bot.on('error', console.error);
                bot.on('kicked', console.error);
    
                bot.once('spawn', () => {
                    process.stdout.write(`${bot.username} `);
                    resolve(bot);
                });
            }
        );
    };
    
    //config.logininterval is set to number 1000
    
    //later in the code...
    function getRandomNameMap(amount) {
        let names = [];
        for (let i = 1; i <= amount; i++) {
            let generatedName = config.crackedusername;
            if (config.userandomsuffix === true) {
                generatedName = generatedName + g.getRandomWords(1, config.randomprefixlength);
            };
            names.push(generatedName);
        };
        return names;
    };
    const usernames = getRandomNameMap(config.crackedamount).map(login => login.split(':'));
    process.stdout.write(`Creating bots: `);
    let botProms = [];
    for (let username of usernames) {
        botProms.push(await makeBot(username));
    }
    bots = (await Promise.allSettled(botProms)).map(({ value, reason }) => value || reason).filter(value => !(value instanceof Error));
    

    Basically, nest a promise but the innermost one iterates over all of the values with a delayed loop.