【问题标题】:NodeJS - how to make forEach and for loop functions sequentialNodeJS - 如何使 forEach 和 for 循环函数顺序
【发布时间】:2018-01-20 12:32:01
【问题描述】:
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"] + '"');
    });
}

我正在使用 Node.js 为名为 Discord 的 VoIP 创建一个音乐机器人,每当执行上述任一循环时,它们都会以随机顺序打印。如何使它们按顺序打印(server.queue[0]、server.queue[1]、server.queue[2]...)? YTDL 是一个名为 ytdl-core 的包,它可以下载 YouTube 视频并使用视频链接显示视频标题等信息。 server.queue 是一组 YouTube 视频链接。

【问题讨论】:

    标签: javascript node.js youtube bots discord


    【解决方案1】:

    简单地说:

    1) 安装:npm i --save async

    2) 和代码:

    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 不是解决异步问题的好方法 - 它会调用它们并运行 for 循环之后的下一条语句

    【讨论】:

      【解决方案2】:

      如果你不想使用async库,你可以像这样使用Promise.all

      const youtubeData = [];
      for (var i = 0; i < server.queue.length; i++) {
        youtubeData.push(YTDL.getInfo(server.queue[i]));
      }
      
      Promise.all(youtubeData).then((values) => {
        // These values will be in the order in which they are called.
      });
      

      请注意,Promise.all 将等待所有查询完成或在一个请求失败时拒绝所有查询。查看您的用例并进行相应选择。

      根据库,如果没有提供回调,它会返回承诺

      ytdl.getInfo(url, [options], [callback(err, info)])

      如果您只想从视频中获取元信息,请使用此选项。如果回调 没有给出,返回一个承诺。

      【讨论】:

        【解决方案3】:

        我一直在努力解决这个问题以找到最佳解决方案,直到我发现了 ECMA6 中表示的内置 yield 功能。因此,使用gen-run 库,您可以执行以下操作:

        let run = require('gen-run');
        
        function notSequential(){
            for (let i = 0; i < 3; i++)
                f(i * 1000);
            console.log("it won't print after for loop");
        }
        
        function sequential(){
            run(function*(){
                for (let i = 0; i < 3; i++)
                    yield changedF(i * 1000);
                console.log("it will print after for loop");
            });
        }
        
        function f(time) {
            setTimeout(function(){
                console.log(time);
            }, time);
        }
        
        function changedF(time) {
            return function (callback) {
                setTimeout(function(){
                    console.log(time);
                    callback();
                }, time);
            }
        }
        
        notSequential();
        

        for 循环后不会打印 0 1000 2000

        sequential();
        

        0 1000 2000 它将在 for 循环后打印

        【讨论】:

          猜你喜欢
          • 2017-12-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-10
          • 1970-01-01
          • 1970-01-01
          • 2023-03-08
          • 2020-03-11
          相关资源
          最近更新 更多