我通过 post 请求调用 getLogs() 并从数据库获取 LogFileID(文件名) 列表,然后我通过调用 _getLogFileUrls 传递此 LogFileID 来执行附加请求,它为我提供了该 ID 的签名 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);
});
}
最佳答案
SQL注入(inject)警报
首先,你的代码存在严重的SQL注入(inject)漏洞。切勿使用字符串连接来使用用户提供的数据创建 SQL,否则任何人都可以读取、修改和删除数据库中的任何内容。这是非常严重的安全问题。有关更多详细信息,请参阅这些答案:
- cannot use backtick when using nodejs 7.3.0
- How to escape mysql special characters with sockets.io/node.js/javascript
答案
现在回答你的问题。要处理您在这里尝试执行的操作,您应该坚持使用回调并使用一个好的模块来处理并发(例如异步):
或者您可以使用带有良好模块的 Promise 来帮助实现并发,例如 Q 或 Bluebird:
此外,在使用 Promise 时,您可以将基于生成器的协程与 co
或 Bluebird.coroutine 等工具结合使用:
或者您可以使用 ES8 async
/await
:
这些是处理像您这样的案例的主要方法。重新发明并发处理的轮子可能会导致(正如您在此处看到的)容易出错且难以维护的代码。
我建议使用正确的工具来完成这项工作。
关于javascript - 循环处理多个请求会导致同步问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45174422/