javascript - 循环处理多个请求会导致同步问题

标签 javascript node.js asynccallback

我通过 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,否则任何人都可以读取、修改和删除数据库中的任何内容。这是非常严重的安全问题。有关更多详细信息,请参阅这些答案:

答案

现在回答你的问题。要处理您在这里尝试执行的操作,您应该坚持使用回调并使用一个好的模块来处理并发(例如异步):

或者您可以使用带有良好模块的 Promise 来帮助实现并发,例如 Q 或 Bluebird:

此外,在使用 Promise 时,您可以将基于生成器的协程与 co 或 Bluebird.coroutine 等工具结合使用:

或者您可以使用 ES8 async/await:

这些是处理像您这样的案例的主要方法。重新发明并发处理的轮子可能会导致(正如您在此处看到的)容易出错且难以维护的代码。

我建议使用正确的工具来完成这项工作。

关于javascript - 循环处理多个请求会导致同步问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45174422/

相关文章:

javascript - PhoneGap本地存储sql删除语句

javascript - React 不会阻止 IE 11 中的表单提交

node.js - Nodejs在内存消息总线中使用EventEmitter进行跨模块通信

javascript - 如何重命名 mongodb 响应键?

javascript - appendTo 不适用于移动设备

javascript - 顺序运行Js代码

node.js - GridDB Node.js 客户端将无法构建

javascript - 无法修改javascript回调中的值

JavaScript 似乎不等待返回值

node.js - 表达多个回调在 app.get 中的工作方式