我通过post请求调用getLogs()并从DB获取LogFileID(filename)列表,然后通过调用_getLogFileUrls传递此LogFileID来执行其他请求,这会给我一个签名的URL作为响应。我将所有这些逐个推入全局数组并返回结束响应。
我知道使用setTimeout不正确但问题没有使用,每次都会给我一个不同的结果。我该怎么做才能解决这个问题?我如何更正此代码,以便只有当签名的URL存储到全局数组中时,循环才会迭代到下一个。
function _getLogFileUrls(logFileId, callback){
var request = require('request'),
config = require('../../config.js');
var fileParams = {
fileName: 'xyzdirectory/' + logFileId
};
request.post({
url: config.filesServiceUrl + 'get-logfile-urls',
json: fileParams
},function(error, response, body) {
if (!error && response.statusCode === 200) {
callback(body);
} else {
res.status(400).send('Error requesting file service for logs:');
}
}).on('error', function(err) {
console.log('File service error for Logs: ' + err);
});
}
function getLogs(req, res){
if(!req.body.id){
return res.status(400).send('Please check the params!');
}
var date;
if(req.body.date){
date = req.body.date;
} else {
date = new Date().toISOString().slice(0,10);
}
var sqlQuery = "SELECT `LogFileID` FROM `logs_data` WHERE `EmpID` = '" + req.body.id + "' AND DATE(`Timestamp`) = '" + date + "'",
resArray= [];
hitThisQueryForMe(sqlQuery, res, function(rows){
if(!rows.length) res.json(rows);
_.each(rows, function(item){
console.log('item: ' + item.LogFileID);
_getLogFileUrls(item.LogFileID, function(response){
resArray.push(response);
});
});
setTimeout(function(){
res.send(resArray);
resArray = [];
}, 4000);
});
}
答案 0 :(得分:1)
首先,您的代码存在严重的SQL注入漏洞。切勿使用字符串连接来使用用户提供的数据创建SQL,否则任何人都可以读取,修改和删除数据库中的任何内容。这是一个非常严重的安全问题。有关详细信息,请参阅以下答案:
现在回答你的问题。要处理你在这里尝试做的事情,你应该坚持回调并使用一个好的模块来处理像Async这样的并发:
或者您可以使用带有良好模块的promises来帮助实现Q或Bluebird等并发性:
此外,在使用promises时,您可以使用基于生成器的协程,使用co
或Bluebird.coroutine等工具:
或者您可以使用ES8 async
/ await
:
这些是处理像你这样的案件的主要方式。重新发明并发处理的轮子可能会导致(如您所见)易于出错,难以维护的代码。
我建议使用合适的工具。
答案 1 :(得分:0)
使用async / await
安装 asyncawait 库及其依赖 bluebird :
npm install asyncawait --save
npm install bluebird --save
您编辑的代码应如下所示:
const async = require('asyncawait/async');
const await = require('asyncawait/await');
const Promise = require('bluebird');
const request = require('request');
const config = require('../../config.js');
function _getLogFileUrls(logFileId) {
return new Promise((resolve, reject) => {
var fileParams = {
fileName: 'xyzdirectory/' + logFileId
};
request.post({
url: config.filesServiceUrl + 'get-logfile-urls',
json: fileParams
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
resolve(body);
} else {
reject('Error requesting file service for logs:');
}
}).on('error', function (err) {
console.log('File service error for Logs: ' + err);
});
});
}
function getLogs(req, res) {
if (!req.body.id) {
return res.status(400).send('Please check the params!');
}
var date;
if (req.body.date) {
date = req.body.date;
} else {
date = new Date().toISOString().slice(0, 10);
}
var sqlQuery = "SELECT `LogFileID` FROM `logs_data` WHERE `EmpID` = '" + req.body.id + "' AND DATE(`Timestamp`) = '" + date + "'",
resArray = [];
hitThisQueryForMe(sqlQuery, res, function (rows) {
if (!rows.length) res.json(rows);
_.each(rows, (async function (item) {
console.log('item: ' + item.LogFileID);
var logFileUrlResponse = await (_getLogFileUrls(item.LogFileID));
resArray.push(logFileUrlResponse);
}));
res.send(resArray);
resArray = [];
});
}