如何从JavaScript查询数据库的for循环返回值?

geturls(data,function(urls){ var data = { "data": [ { "userProfile": userP }, { "urls": urls } ] }; res.send(data); }); function getUrls(data,done){ links = new Array(); for (var i=0; i<data.length; i++){ user = data[i] Url.find({where:{data.id}}).success(function(url){ links.push({ "url": ur.text, "date": data.syncedTime }); if (urls.length == data.length){ done(links); } }); } } 

我的问题与我的代码是这样的:

一旦我的数组收集的数据等于父数组的长度,我通过callback返回响应。 这显然是一个非常危险的,不是很优雅的解决scheme。 因为,假设我从Url数据库中得到一个.failure,那么我的urls.length将不会和data.length一样。 所以,我有点困惑如何去做这件事。 任何帮助?

如果你使用async.js ,对你来说很容易。

我在这里使用mapSeries 。 它需要3个参数。

  • 收集/arrays
  • 迭代器,这将被传递给具有2个参数的传递集合/数组中的每个项目。 1.collections品,2.回拨。 在迭代器中完成作业之后,您应该调用节点样式的callback函数(首先,结果如下)。
  • 最终callback,将在映射集合中的所有项目之后调用。

 function getUrls(data,done){ var async = require('async'); async.mapSeries(data, function(user, cb) {//If you want it to be async `async.map` Url.find({where:{user.id}}).success(function(url){ cb(null, { "url": url.text, "date": user.syncedTime }); }); }, function(err, results) { //results is an array. Its the same as `links` in your old code. done(results); }); } geturls(data,function(urls){ var data = { "data": [ { "userProfile": userP }, { "urls": urls } ] }; res.send(data); }); 

使用recursion:

 function getUrls(data,done) { var links = new Array(); function doGetUrl(i) { var user = data[i]; Url.find({where:{data.id}}). success(function(url){ links.push({ "url": ur.text, "date": data.syncedTime }); if (links.length == data.length){ done(links); } else { doGetUrl(i + 1); // get next url } }). failure(function(err) { doGetUrl(i); // on error, try to get current url again // other error handling code }); } doGetUrl(0); } 

我可能会使用完整的callback,在jQuery的条款。 有一个logging有多lesslogging已经处理的计数器,并且完整地更新这个logging,因为这在成功或失败时执行。 然后,当该计数器> =数据数组的长度,您可以退出。

顺便说一句,我会一直在做一个> =,而不是一个==你在那里做的比较,这样,如果出于任何疯狂的原因,计数比你应该退出更多的提高。

如果你想要做的是避免检查links.length来确定你什么时候完成的问题,那么我认为它只是添加一个单独的计数器,即使urk数据库失败也会增加。 如果你这样做,你可以继续使用当前的asynchronous请求并行运行。

 var nreq = 0; for (var i=0; i<data.length; i++){ doTheAsyncOperation(function(){ //Run this part in both the success and error cases nreq = nreq + 1; if(nreq >= data.length){ done(links) } }) } 

另一方面,如果你想在另一个之后运行一个查询,你将需要重写for来使用recursion。 这一次,您不必担心保留一个单独的计数器,因为您知道最终请求的运行时间:

 function loop(i){ if(i >= data.length){ done(links); }else{ doTheAsyncOperation(function(){ loop(i+1); }) } } loop(0); 

最后,它很好地知道如何编码这种模式,但从长远来看,我强烈build议使用控制stream库来保持清洁。