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发送时为空;怎么取改写上面的代码?


11 回复

当然可以。在 Node.js 中处理异步操作时,特别是涉及到循环中的异步任务,我们需要确保所有异步任务都完成后再执行下一步操作。这可以通过使用 async/awaitPromise 来实现。下面是一个改进后的代码示例:

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('')); // 将数据以字符串形式发送
    }
});

解释:

  1. 引入async库:我们引入了async库来帮助管理异步操作。async.eachOfSeries方法用于按顺序执行异步任务。

  2. 初始化data数组:我们将data初始化为一个空数组,而不是字符串。这是因为字符串在JavaScript中是不可变的,频繁的拼接会导致性能问题。

  3. 使用async.eachOfSeriesasync.eachOfSeries方法接收三个参数:待处理的数组、一个处理函数(该函数接收当前值、索引和回调函数作为参数)、以及一个完成后的回调函数。

  4. 异步数据库查询:在处理函数内部,我们进行数据库查询。当查询完成后,我们检查是否有结果,并将符合条件的结果添加到data数组中。

  5. 调用回调函数:每次查询完成后,我们调用callback()函数来通知async.eachOfSeries方法该任务已完成。

  6. 完成后的回调:最后,我们在外部的回调函数中处理可能的错误或成功发送数据。

通过这种方式,我们可以确保所有的异步操作都完成后再发送最终的数据。


用闭包

是这样吧, 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 次操作已经完成

我在另一个贴中的回复: 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/awaitPromise.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 到前端之前,所有的异步查询都已经完成。

回到顶部