Nodejs for循环语句里面的异步操作怎么写?
Nodejs for循环语句里面的异步操作怎么写?
有一个数组results1,从数组取出每个数循环去查询数据库判断是否存在…如果存在添加到另一个参数data中, 最后循环操作完毕 把data2发送到前端。 已知数组results var telephone = results[0]; var data=’’; for( i = 1; i < results1.length; i++) { var recto=telephone.substr(0,7); mobileModel.Mobile.findOne({‘YJPhone’:recto},function(err,mresult){ if(mresult){ data+=recto; } }
} res.send(data); 因为查询数据库是异步操作,data发送时为空;怎么取改写上面的代码?
当然可以。在 Node.js 中处理异步操作时,特别是涉及到循环中的异步任务,我们需要确保所有异步任务都完成后再执行下一步操作。这可以通过使用 async/await
和 Promise
来实现。下面是一个改进后的代码示例:
const async = require('async'); // 引入async库来帮助管理异步操作
// 假设mobileModel是已经定义好的Mongoose模型
var data = [];
// 使用async.eachOfSeries来处理异步循环操作
async.eachOfSeries(results1, (value, index, callback) => {
var recto = value.substr(0, 7);
mobileModel.Mobile.findOne({'YJPhone': recto}, (err, mresult) => {
if (!err && mresult) {
data.push(recto);
}
// 完成当前循环项后调用回调函数
callback();
});
}, (err) => {
if (err) {
console.error('An error occurred:', err);
res.status(500).send('Internal Server Error');
} else {
res.send(data.join('')); // 将数据以字符串形式发送
}
});
解释:
-
引入async库:我们引入了
async
库来帮助管理异步操作。async.eachOfSeries
方法用于按顺序执行异步任务。 -
初始化data数组:我们将
data
初始化为一个空数组,而不是字符串。这是因为字符串在JavaScript中是不可变的,频繁的拼接会导致性能问题。 -
使用async.eachOfSeries:
async.eachOfSeries
方法接收三个参数:待处理的数组、一个处理函数(该函数接收当前值、索引和回调函数作为参数)、以及一个完成后的回调函数。 -
异步数据库查询:在处理函数内部,我们进行数据库查询。当查询完成后,我们检查是否有结果,并将符合条件的结果添加到
data
数组中。 -
调用回调函数:每次查询完成后,我们调用
callback()
函数来通知async.eachOfSeries
方法该任务已完成。 -
完成后的回调:最后,我们在外部的回调函数中处理可能的错误或成功发送数据。
通过这种方式,我们可以确保所有的异步操作都完成后再发送最终的数据。
用闭包
是这样吧, var telephone = results[0]; results1.forEach(function (result){ var recto=telephone.substr(0,7); mobileModel.Mobile.findOne({‘YJPhone’:recto},function(err,mresult){ if(mresult){ data+=recto; } } }
eventproxy +1
简单的方案是每次取回数据以后手动标记, 用来判断是否对应 result1 次操作已经完成
async
我在另一个贴中的回复: http://cnodejs.org/topic/524558f6f29c7bbd3c5c63c8
then.js的写法如下:
// url_list 为数组
then.each(url_list, function (defer, url) {
request(url, function (err, res, json) {
defer(err, json)
})
}).then(function (defer, result) {
// result 就是url获取的json结果数组,顺序与url对应
}).fail(function (defer, err) {
// 处理 err
})
https://github.com/teambition/then.js 目前teambition.com前端和angularjs.cn的后端采用的then.js
把操作放入数组func然后用async.parallel也可以吧? each(results1 ,function(results){func.push(function(callbak){…}}) async.parallel(func,function()…
推荐一篇博文,关于 async 的:http://freewind.me/blog/20120515/917.html
用async吧
用promise, like this
function db(req, res){
var ps = [];
for(var k in models){
(function(k){
ps.push(
models[k].find().exec().then(function(v){
return {collection: k, data: v};
})
);
})(k);
}
Q.all(ps).then(function(a){
res.send(a);
}, function(){
res.send('未知错误');
});
}
在这个问题中,你需要处理的是在 for
循环中的异步操作。使用传统的 for
循环会导致异步操作没有完成时就执行了 res.send(data)
。因此,你需要等待所有的异步操作完成后再发送数据。
这里是一个改进后的代码示例,使用了 async/await
和 Promise.all
来确保所有异步操作都已完成:
const async = require('async');
var telephone = results[0];
var data = [];
var tasks = [];
for (let i = 1; i < results1.length; i++) {
let recto = telephone.substr(0, 7);
tasks.push(
new Promise((resolve, reject) => {
mobileModel.Mobile.findOne({ 'YJPhone': recto }, function (err, mresult) {
if (err) return reject(err);
if (mresult) {
resolve(recto);
} else {
resolve(null); // 或者可以忽略不存的情况
}
});
})
);
}
Promise.all(tasks)
.then(results => {
// 过滤出非空的结果
const filteredResults = results.filter(result => result !== null);
res.send(filteredResults.join(','));
})
.catch(err => {
console.error(err);
res.status(500).send("An error occurred");
});
解释:
- 我们使用了一个
tasks
数组来存储所有的Promise
对象。 - 每次循环时,创建一个新的
Promise
,并在查询数据库后根据结果解析该Promise
。 - 使用
Promise.all(tasks)
等待所有异步操作完成。 - 最后将过滤后的结果发送给前端。
这样可以确保在发送 data
到前端之前,所有的异步查询都已经完成。