如何在for循环中等待每次迭代并在nodeJS中将响应作为API响应返回
Posted
技术标签:
【中文标题】如何在for循环中等待每次迭代并在nodeJS中将响应作为API响应返回【英文标题】:How to wait for each iteration in for loop and return response as API response in nodeJS 【发布时间】:2018-02-27 20:42:40 【问题描述】:我正在使用 for 循环遍历元素数组并在 for 循环内调用具有不同参数的相同函数。这是我的代码:
exports.listTopSongs = function(query)
return new Promise(function(resolve, reject)
var str = query.split(","), category,
for(var i=0; i<str.length; i++)
sampleFn(str[i], 'sample', resolve, reject);
);
;
function sampleFn(lang, cat, resolve, reject)
client.on("error", function (err)
console.log(err);
var err = new Error('Exception in redis client connection')
reject(err);
);
client.keys(lang, function (err, keys)
if (err) return console.log(err);
if(keys.length != 0)
client.hgetall(keys, function (error, value)
var objects = Object.keys(value);
result['title'] = lang;
result[cat] = [];
var x =0;
for(x; x<objects.length; x++)
var val = objects[x];
User.findAll(attributes: ['X', 'Y', 'Z'],
where:
A: val
).then(data =>
if(data != null)
//some actions with data and stored it seperately in a Json array
if(result[cat].length == objects.length)
resolve(result);
else
console.log(""+cat+" is not avilable for this value "+data.dataValues['X']);
);
);
);
这里它不会等待第一次迭代完成。它只是在完成第一次迭代功能之前异步运行。我需要将结果作为结果返回:[ 1, 2, 3,4]。但它无缝运行并在完成所有操作之前返回空对象或仅返回一个对象。如何解决。
我使用了节点异步循环。但它使用下一个,我无法在使用该包时发送我的参数。请帮帮我
【问题讨论】:
检查“aync”包。它有许多使 for 循环同步运行的功能。 你使用的是哪个node js版本? 我使用的是节点 8.4.0 好的,@ShubhamJain 会尽力让你知道 【参考方案1】:Async 提供了允许这样做的控制流方法。
使用async.each:
async.each(openFiles, function(file, callback)
// Perform operation on file here.
console.log('Processing file ' + file);
if( file.length > 32 )
console.log('This file name is too long');
callback('File name too long');
else
// Do work to process file here
console.log('File processed');
callback();
, function(err)
// if any of the file processing produced an error, err would equal that error
if( err )
// One of the iterations produced an error.
// All processing will now stop.
console.log('A file failed to process');
else
console.log('All files have been processed successfully');
);
【讨论】:
【参考方案2】:如果您不想使用库,可以自己编写代码。这也会很有启发性。我接受了您的问题并编写了一个虚拟异步循环:
function listTopSongs(query)
return new Promise(async(resolve, reject) => //add async here in order to do asynchronous calls
const str = query.split(",") //str is const, and the other variable was not used anyway
for( let i = 0;i < str.length; i++)
const planet = await sampleFn(str[i], 'sample', resolve, reject)
console.log(planet)
);
;
function sampleFn(a, b, c, d)
return fetch(`https://swapi.co/api/planets/$a/`)
.then(r => r.json())
.then(rjson => (a + " : " + rjson.name))
listTopSongs("1,2,3,4,5,6,7,8,9")
我使用了一些虚拟的星球大战 API 来伪造一个长期承诺,但它应该适用于您的 sampleFn。小心,如果你有像示例中那样的网络调用,它会非常非常慢。
编辑:我运行了你的代码,发现有一些错误:你的承诺中没有解决,所以它不是一个 thenable (https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Global_Objects/Promise/resolve see thenable )
这是一个完整的工作代码。好的部分:不需要库,没有依赖项。
//for node.js, use node-fetch :
//const fetch = require("node-fetch")
function listTopSongs(query)
return new Promise(async(resolve, reject) => //add async here in order to do asynchronous calls
const str = query.split(",") //str is const, and the other variable was not used anyway
const planets = []
for (let i = 0; i < str.length; i++)
const planet = await sampleFn(i + 1, str[i], resolve, reject)
planets[i] = planet
console.log(planet)
resolve(planets)
);
;
function sampleFn(a, b, c, d)
return fetch(`https://swapi.co/api/planets/$a/`)
.then(r => r.json())
.then(rjson => (a + b + " : " + rjson.name))
listTopSongs("a,b,c,d").then(planets => console.log(planets))
【讨论】:
我无法将我的 json 数组从函数 sampleFn 返回到 listTopSongs【参考方案3】:由于你使用的是promise,你可以做这样的事情
exports.listTopSongs = function(query)
return Promise.resolve(true).then(function()
var str = query.split(",");
var promises = str.map(function(s)
return sampleFn(str[i], 'sample');
);
return Promise.all(promises);
).then(function(results)
//whatever you want to do with the result
);
;
为此,您必须将 sampleFn 更改为不依赖外部解析和拒绝函数。我看不出使用外部解决和拒绝的原因。为什么不使用 Promise.Resolve, Promise.Reject;
【讨论】:
以上是关于如何在for循环中等待每次迭代并在nodeJS中将响应作为API响应返回的主要内容,如果未能解决你的问题,请参考以下文章
NodeJS,如何强制异步 for 循环在传递到下一次迭代之前等待 HTTP 请求解决,这样我们就不会收到 EMFILE 错误?