根据最新的响应发送Node中的同步请求

我在我的Node服务器上使用asynchronous模块,以循环遍历MongoDB数据库中的对象,根据每个对象中的数据发出对Instagram API的请求,并在每次迭代中增加minTimestamp ,直到达到endTimestamp

下面的代码工作很好,除了一个大问题。 如果我通过一个硬编码的值( minTimestamp += 1000 )来增加minTimestamp ,那么所有的运行都很好。 然而,当我改变这一行代码来抓取最新的响应( minTimestamp = images[0].created_time )的最新created_time我的循环运行一次为每个'事件'然后停止。 我得到正确的递增的minTimestamplogging到我的控制台,但值似乎永远不会到下一个循环。

 // modules ================================================= var express = require('express.io'); var app = express(); var port = process.env.PORT || 6060; var io = require('socket.io').listen(app.listen(port)); var request = require('request'); var Instagram = require('instagram-node-lib'); var mongoose = require('mongoose'); var async = require('async'); var bodyParser = require('body-parser'); var methodOverride = require('method-override'); var db = require('./config/db'); var Event = require('./app/models/event'); // configuration =========================================== mongoose.connect(db.url); // connect to our mongoDB database // get all data/stuff of the body (POST) parameters app.use(bodyParser.json()); // parse application/json app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json app.use(bodyParser.urlencoded({ extended: true })); // parse application/x-www-form- urlencoded app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method- Override header in the request. simulate DELETE/PUT app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users var baseUrl = 'https://api.instagram.com/v1/media/search?lat='; var clientId = CLIENT-ID; Event.find({}, function(err, events) { async.eachSeries(events, function(event, seriesCallback) { var name = event.event; var latitude = event.latitude; var longitude = event.longitude; var distance = event.radius; var minTimestamp = Math.floor(new Date(event.start).getTime()/1000); var endTimestamp = Math.floor(new Date(event.end).getTime()/1000); async.whilst( function () { return minTimestamp < Math.floor(Date.now() / 1000) && minTimestamp < endTimestamp; }, function(requestFinishedCallback) { console.log('sending request to Instagram for ' + name + ' with min_timestamp: ' + minTimestamp); request(baseUrl + latitude + '&lng=' + longitude + '&distance=' + distance + '&min_timestamp=' + minTimestamp + '&client_id=' + clientId, function (error, response, body) { if (error) { console.log('error'); return; } //JSON object with all the info about the image var imageJson = JSON.parse(body); var images = imageJson.data; var numImages = images.length; if (numImages > 0) { console.log(numImages + ' images returned with starting time ' + images[(numImages - 1)].created_time + ' and ending time ' + images[0].created_time); } async.eachSeries(images, function(image, imageFinishedCallback) { //Save the new object to DB Event.findOneAndUpdate( { $and: [{latitude: latitude}, {radius: distance}] }, { $push: {'photos': { img: image.images.standard_resolution.url, link: image.link, username: image.user.username, profile: image.user.profile_picture, text: image.caption ? image.caption.text : '', longitude: image.location.longitude, latitude: image.location.latitude }}}, { safe: true, upsert: false }, function(err, model) { console.log(err); } ); imageFinishedCallback(); }, function(err){ // if any of the image 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('Images failed to process'); } else { console.log('Images processed'); } }); // this works minTimestamp += 1000; // this does not // minTimestamp = images[0].created_time; if (numImages > 0) { console.log(numImages + 'images have been processed successfully and min_timestamp has been incremented to: ' + minTimestamp); } requestFinishedCallback(); } ); }, function(err){ // if any of the image 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('Event failed to process'); } else { console.log(name + ' has been fully processed successfully with final min_timestamp of: ' + minTimestamp); } } ); seriesCallback(); }, function(err){ // if any of the image 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('Something failed to process'); } else { console.log('All events have been processed successfully'); } } ); }); // routes ================================================== require('./app/routes')(app); // configure our routes // start app =============================================== console.log('Magic happens on port ' + port); // shoutout to the user exports = module.exports = app; 

如果你有一个git repo,我可以看看,我可以更好地debugging,但是…说,我看到两个明显的问题:

  1. 虽然你正在做一个async.eachSeries,你不等待完成findOneAndUpdate调用。

你的例子:

 Event.findOneAndUpdate( {}, {}, function(err, model) { console.log(err); } ); imageFinishedCallback(); 

应该变成这样:

 Event.findOneAndUpdate( {}, {}, function(err, model) { console.log(err); imageFinishedCallback(); } ); 
  1. 类似于第一个问题,但与async.whilstcallback。 您正在调用async.eachSeries,但是会立即转到下一个循环。

你的代码:

 function (error, response, body) { // ... async.eachSeries(images, function(image, imageFinishedCallback) {/* ... */}, function(err){ // ... }); // this works minTimestamp += 1000; // this does not // minTimestamp = images[0].created_time; if (numImages > 0) { console.log(numImages + 'images have been processed successfully and min_timestamp has been incremented to: ' + minTimestamp); } requestFinishedCallback(); } 

应改为:

 function (error, response, body) { // ... async.eachSeries(images, function(image, imageFinishedCallback) {/* ... */}, function(err){ // ... console.log(numImages + 'images have been processed successfully and min_timestamp has been incremented to: ' + minTimestamp); minTimestamp = images[0].created_time; requestFinishedCallback(); }); } 

如果你有一个github repo来发布我可以进一步debugging,但是…看起来问题来自于不等待asynchronous函数完成。