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
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