根据最新响应在 Node 中发送同步请求
Send synchronous requests in Node based on latest response
我在我的节点服务器上使用 async 模块来循环遍历我的 mongodb 数据库中的对象,根据其中的数据触发对 Instagram API 的请求每个对象,并在每次迭代时递增 minTimestamp
,直到达到 endTimestamp
。
除了一个大问题外,下面的代码工作得很好。如果我将 minTimestamp
增加一个硬编码值 (minTimestamp += 1000
),一切运行良好。但是,当我更改那一行代码以从最近的响应 (minTimestamp = images[0].created_time
) 中获取最新的 created_time
时,我的循环针对每个 'event' 运行一次然后停止。我将正确的增量 minTimestamp
记录到我的控制台,但该值似乎永远不会进入下一个循环。
// 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 回购协议我可以看看,我可以更好地调试它,但是......也就是说,我看到两个明显的问题:
- 尽管您正在执行 async.eachSeries,但您并未等待完成 findOneAndUpdate 调用。
你的例子:
Event.findOneAndUpdate( {}, {},
function(err, model) {
console.log(err);
}
);
imageFinishedCallback();
应该变成这样:
Event.findOneAndUpdate( {}, {},
function(err, model) {
console.log(err);
imageFinishedCallback();
}
);
- 与第一个问题类似,但有
async.whilst
回调。您正在调用 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 回购到 post 我可以进一步调试,但是......看起来问题是因为没有等待异步函数完成。
我在我的节点服务器上使用 async 模块来循环遍历我的 mongodb 数据库中的对象,根据其中的数据触发对 Instagram API 的请求每个对象,并在每次迭代时递增 minTimestamp
,直到达到 endTimestamp
。
除了一个大问题外,下面的代码工作得很好。如果我将 minTimestamp
增加一个硬编码值 (minTimestamp += 1000
),一切运行良好。但是,当我更改那一行代码以从最近的响应 (minTimestamp = images[0].created_time
) 中获取最新的 created_time
时,我的循环针对每个 'event' 运行一次然后停止。我将正确的增量 minTimestamp
记录到我的控制台,但该值似乎永远不会进入下一个循环。
// 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 回购协议我可以看看,我可以更好地调试它,但是......也就是说,我看到两个明显的问题:
- 尽管您正在执行 async.eachSeries,但您并未等待完成 findOneAndUpdate 调用。
你的例子:
Event.findOneAndUpdate( {}, {},
function(err, model) {
console.log(err);
}
);
imageFinishedCallback();
应该变成这样:
Event.findOneAndUpdate( {}, {},
function(err, model) {
console.log(err);
imageFinishedCallback();
}
);
- 与第一个问题类似,但有
async.whilst
回调。您正在调用 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 回购到 post 我可以进一步调试,但是......看起来问题是因为没有等待异步函数完成。