NodeJS - 如何使 forEach 和 for 循环函数顺序化

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"] + '"');
    });
}

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

简单地说:

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 loop

之后的下一个语句

如果不想使用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 将等待所有查询完成或在一个请求失败时拒绝一切。查看您的用例并相应地 select。

根据图书馆,它returns承诺如果没有提供回调

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

Use this if you only want to get metainfo from a video. If callback isn't given, returns a promise.

我为这个问题苦苦挣扎了一段时间以找到最佳解决方案,直到我发现了 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();

it won't print after for loop 0 1000 2000

sequential();

0 1000 2000 it will print after for loop