javascript - How do I write a synchronous while loop using node.js and promises -
i call function takes data every student specific time interval , repeat same process until reaches condition.
the current code seems make parallel calls function iteratethruallstudents();
my code looks this:
var startdate = new date("march 16, 2016 00:00:00"); //start february var fromtimestamp = null; var totimestamp = null; var today = new date(); var todaytimestamp = new date(today).gettime() / 1000; async.whilst( function () { return fromtimestamp < todaytimestamp; }, function (callback) { console.log(startdate); fromtimestamp = new date(startdate).gettime() / 1000; startdate.setdate(startdate.getdate() + 5); totimestamp = new date(startdate).gettime() / 1000; iteratethruallstudents(fromtimestamp, totimestamp); callback(null, startdate); }, function (err, n) { console.log('finished ' + n); } ); function iteratethruallstudents(from, to) { student.find({status: 'student'}) .populate('user') .exec(function (err, students) { if (err) { throw err; } var counter = 0; async.eachseries(students, function iteratee(student, callback) { if (student.worksnap.user != null) { var worksnapoptions = { hostname: 'api.worksnaps.com', path: '/api/projects/' + project_id + '/time_entries.xml?user_ids=' + student.worksnap.user.user_id + '&from_timestamp=' + + '&to_timestamp=' + to, headers: { 'authorization': 'basic ' + auth_hash }, method: 'get' }; gettimeentries(worksnapoptions) .then(function (response) { //callback invoked on deferred.resolve return convertxmltojson(response); }).then(function (timeentries) { console.log('convert xml json'); var isempty = _.isempty(timeentries); // true if (isempty) { callback(null); } return savetimeentry(timeentries); }).then(function (response) { counter++; console.log('all timeentries 1 student finished....student: ' + student.worksnap.user.user_id + ' student counter: ' + counter); callback(null); }); } else { callback(null); } }); }); } function convertxmltojson(response) { var deferred = q.defer(); parser.parsestring(response, function (err, results) { if (err) { deferred.reject(err); } var json_string = json.stringify(results.time_entries); var timeentries = json.parse(json_string); deferred.resolve(timeentries); }); return deferred.promise; } function savetimeentry(timeentries) { var deferred = q.defer(); _.foreach(timeentries.time_entry, function (item) { student.findone({ 'worksnap.user.user_id': item.user_id[0] }) .populate('user') .exec(function (err, student) { if (err) { deferred.reject(err); } student.worksnap.timeentries.push(item); student.save(function (err) { if (err) { deferred.reject(err); } else { //console.log(item); } }); }); }); deferred.resolve('finished saving timeentries 1 student...'); return deferred.promise; } function gettimeentries(requestoptions) { //create deferred object q process.env.node_tls_reject_unauthorized = "0"; var deferred = q.defer(); var req = http.request(requestoptions, function (response) { //set response encoding parse json string response.setencoding('utf8'); var responsedata = ''; //append data responsedata variable on 'data' event emission response.on('data', function (data) { responsedata += data; }); //listen 'end' event response.on('end', function () { //resolve deferred object response console.log('http call finished'); deferred.resolve(responsedata); }); }); //listen 'error' event req.on('error', function (err) { //if error occurs reject deferred console.log('inside on error.'); console.log(err); deferred.reject(err); }); req.end(); //we returning promise object //if returned deferred object //deferred object reject , resolve potentially modified //violating expected behavior of function return deferred.promise; }
anyone has idea how achieve such thing can grab data students synchronously each time interval?
take @ docs async.eachseries() (alias of #each()
). you'll want supply third argument, , call callback originating argument in second function of async.whilst()
.
i think following modifications need. take callback named done
, specifically:
var startdate = new date("march 16, 2016 00:00:00"); //start february var fromtimestamp = null; var totimestamp = null; var today = new date(); var todaytimestamp = new date(today).gettime() / 1000; async.whilst( function () { return fromtimestamp < todaytimestamp; }, function (callback) { console.log(startdate); fromtimestamp = new date(startdate).gettime() / 1000; startdate.setdate(startdate.getdate() + 5); totimestamp = new date(startdate).gettime() / 1000; iteratethruallstudents(fromtimestamp, totimestamp, callback); }, function (err, n) { console.log('finished ' + n); } ); function iteratethruallstudents(from, to, done) { student.find({status: 'student'}) .populate('user') .exec(function (err, students) { if (err) { throw err; } var counter = 0; async.eachseries(students, function iteratee(student, callback) { if (student.worksnap.user != null) { var worksnapoptions = { hostname: 'api.worksnaps.com', path: '/api/projects/' + project_id + '/time_entries.xml?user_ids=' + student.worksnap.user.user_id + '&from_timestamp=' + + '&to_timestamp=' + to, headers: { 'authorization': 'basic ' + auth_hash }, method: 'get' }; gettimeentries(worksnapoptions) .then(function (response) { //callback invoked on deferred.resolve return convertxmltojson(response); }).then(function (timeentries) { console.log('convert xml json'); var isempty = _.isempty(timeentries); // true if (isempty) { callback(null); } return savetimeentry(timeentries); }).then(function (response) { counter++; console.log('all timeentries 1 student finished....student: ' + student.worksnap.user.user_id + ' student counter: ' + counter); callback(null); }); } else { callback(null); } }, function eachseriesfinished(err) { if (err) return done(err); return done(null, to); }); }); } function convertxmltojson(response) { var deferred = q.defer(); parser.parsestring(response, function (err, results) { if (err) { deferred.reject(err); } var json_string = json.stringify(results.time_entries); var timeentries = json.parse(json_string); deferred.resolve(timeentries); }); return deferred.promise; } function savetimeentry(timeentries) { var deferred = q.defer(); _.foreach(timeentries.time_entry, function (item) { student.findone({ 'worksnap.user.user_id': item.user_id[0] }) .populate('user') .exec(function (err, student) { if (err) { deferred.reject(err); } student.worksnap.timeentries.push(item); student.save(function (err) { if (err) { deferred.reject(err); } else { //console.log(item); } }); }); }); deferred.resolve('finished saving timeentries 1 student...'); return deferred.promise; } function gettimeentries(requestoptions) { //create deferred object q process.env.node_tls_reject_unauthorized = "0"; var deferred = q.defer(); var req = http.request(requestoptions, function (response) { //set response encoding parse json string response.setencoding('utf8'); var responsedata = ''; //append data responsedata variable on 'data' event emission response.on('data', function (data) { responsedata += data; }); //listen 'end' event response.on('end', function () { //resolve deferred object response console.log('http call finished'); deferred.resolve(responsedata); }); }); //listen 'error' event req.on('error', function (err) { //if error occurs reject deferred console.log('inside on error.'); console.log(err); deferred.reject(err); }); req.end(); //we returning promise object //if returned deferred object //deferred object reject , resolve potentially modified //violating expected behavior of function return deferred.promise; }
side note, if open it, using co
or async/await
simplify code lot, in opinion.
Comments
Post a Comment