Search code examples
javascriptnode.jsyoutubebotsdiscord

NodeJS - how to make forEach and for loop functions sequential


server.queue.forEach(function(q) {
    YTDL.getInfo(q, (error, info) => {
        console.log(info["title"]);
        message.reply('"' + info["title"] + '"');
    });
});

for (var i = 0; i < server.queue.length; i++) {
    YTDL.getInfo(server.queue[i], (error, info) => {
         console.log(info["title"]);
         message.reply('"' + info["title"] + '"');
    });
}

I'm creating a music bot for a VoIP called Discord using Node.js and whenever either of the loops above execute, they print in a random order. How do I make it so that they are printed sequentially (server.queue[0], server.queue[1], server.queue[2]...)? YTDL is a package called ytdl-core that downloads YouTube videos as well as display the info such as the title of a video using the video link. server.queue is an array of YouTube video links.


Solution

  • Just to add why you try to make it sequential: YouTube has rate limits and etc limitations which can be easily broken if there will be parallel calls.

    So for that reason we are not using Promise.all or .allSettled.

    Solution to question based on modules and language features of stack for the year 2017:

    1. install: npm i --save async

    2. and the code:

    const async = require('async');
        
    async.eachSeries(
      server.queue,
      (q, next) => {
        YTDL.getInfo(q, (error, info) => {
            console.log(info["title"]);
            message.reply('"' + info["title"] + '"');
            next();
        });
      }
    });
    

    for..loop is not good solution for asynchronous stuff - it will call them and run next statements that comes after for loop.


    Question is dated for the year 2017, for that moment there was no proper support of async/await methods and etc. Plus people were staying at LTS versions of Node.js which slowed down progress.