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

Posted

技术标签:

【中文标题】NodeJS - 如何使 forEach 和 for 循环函数顺序【英文标题】:NodeJS - how to make forEach and for loop functions sequential 【发布时间】: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 视频链接。

【问题讨论】:

【参考方案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 循环后打印

【讨论】:

以上是关于NodeJS - 如何使 forEach 和 for 循环函数顺序的主要内容,如果未能解决你的问题,请参考以下文章

如何在 TypeScript 中打破 ForEach 循环

nodejs中的异步foreach和mongoose

如何使我的类可迭代,以便我可以使用 foreach 语法?

如何使 SQLite 与 Angular 4+、Electron 和 NodeJS 一起工作

NodeJs Twig ForEach无效

NodeJS - 控制器 - 来自集合的多个查询 + forEach