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

3
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视频链接的数组。
3个回答

3

简单来说:

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不是异步操作的好解决方案 - 它会调用它们并运行紧随其后的下一条语句。


0

我曾经为了找到最佳解决方案而苦苦挣扎,直到我发现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 循环结束后会被打印出来。

0

如果您不想使用 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)])

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接