![](/img/trans.png)
[英]How to deal with an if statement using promises or synchronous calls in node.js
[英]How do I write a synchronous while loop using node.js and promises
我想调用一个函数,它为每个学生提供特定时间间隔的数据,并重复相同的过程,直到达到某种条件。
它当前的代码似乎对函数iterateThruAllStudents()进行了并行调用;
我的代码看起来像这样:
var startDate = new Date("March 16, 2016 00:00:00"); //Start from 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 for ' + 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=' + from + '&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 to json');
var isEmpty = _.isEmpty(timeEntries); // true
if (isEmpty) {
callback(null);
}
return saveTimeEntry(timeEntries);
}).then(function (response) {
counter++;
console.log('all timeEntries for one 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 for one student...');
return deferred.promise;
}
function getTimeEntries(requestOptions) {
//create a deferred object from Q
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var deferred = Q.defer();
var req = http.request(requestOptions, function (response) {
//set the response encoding to parse json string
response.setEncoding('utf8');
var responseData = '';
//append data to responseData variable on the 'data' event emission
response.on('data', function (data) {
responseData += data;
});
//listen to the 'end' event
response.on('end', function () {
//resolve the deferred object with the response
console.log('http call finished');
deferred.resolve(responseData);
});
});
//listen to the 'error' event
req.on('error', function (err) {
//if an error occurs reject the deferred
console.log('inside On error.');
console.log(err);
deferred.reject(err);
});
req.end();
//we are returning a promise object
//if we returned the deferred object
//deferred object reject and resolve could potentially be modified
//violating the expected behavior of this function
return deferred.promise;
}
任何人都知道如何实现这样的事情,我可以为每个时间间隔同步获取所有学生的数据?
看一下async.eachSeries()的文档( #each()
别名)。 您将要提供第三个参数,并在async.whilst()
的第二个函数中调用源自该参数的回调。
我认为以下修改将满足您的需求。 看一下我命名done
的回调,具体来说:
var startDate = new Date("March 16, 2016 00:00:00"); //Start from 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 for ' + 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=' + from + '&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 to json');
var isEmpty = _.isEmpty(timeEntries); // true
if (isEmpty) {
callback(null);
}
return saveTimeEntry(timeEntries);
}).then(function (response) {
counter++;
console.log('all timeEntries for one 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 for one student...');
return deferred.promise;
}
function getTimeEntries(requestOptions) {
//create a deferred object from Q
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var deferred = Q.defer();
var req = http.request(requestOptions, function (response) {
//set the response encoding to parse json string
response.setEncoding('utf8');
var responseData = '';
//append data to responseData variable on the 'data' event emission
response.on('data', function (data) {
responseData += data;
});
//listen to the 'end' event
response.on('end', function () {
//resolve the deferred object with the response
console.log('http call finished');
deferred.resolve(responseData);
});
});
//listen to the 'error' event
req.on('error', function (err) {
//if an error occurs reject the deferred
console.log('inside On error.');
console.log(err);
deferred.reject(err);
});
req.end();
//we are returning a promise object
//if we returned the deferred object
//deferred object reject and resolve could potentially be modified
//violating the expected behavior of this function
return deferred.promise;
}
旁注,如果你对它开放,使用像co
或async/await
这样的东西会在我看来很多地简化这段代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.