节点JS请求阻止其他请求

时间:2017-11-17 06:25:17

标签: javascript node.js promise mean-stack es6-promise

我创建了Node JS应用程序,我明确地从数据库下载了超过100000条记录。当请求正在进行时,我尝试从另一个浏览器登录相同的应用程序,除非先前的请求完成,否则它不会响应。任何的想法 ?与事件循环或线程有什么关系? 所以这是我的逻辑。 我在步骤1中向我的API发出get请求,在步骤2中调用API数据库层。数据库只返回21条记录,我显式循环100000 * 21以进行大量渲染,以测试json2csv上的负载。执行此操作时,对服务器的其他请求将不会响应,直到最后一个处理完成。

Step 1:

router.get('/report/downloadOverdueTrainings/:criteria', function (req, res, next) {
        var overDueTrainings = [];
        var reportManager = new ReportManager();
        var result = reportManager.getOverdueTrainings(JSON.parse(req.params.criteria));
        result.then(function (result) {
            var fields = ['Over Due Trainings'];
            for (var i = 0; i < 100000; i++) { //Testing purpose
                for (var training of result) {
                    overDueTrainings.push({
                        'Over Due Trainings': training.OverDueTrainings
                    })
                }
            }
            json2csv({
                data: overDueTrainings,
                fields: fields
            }, function (err, csv) {
                if (err)
                    throw err;
                res.setHeader('Content-disposition', 'attachment; filename=OverdueTrainings.csv');
                res.set('Content-Type', 'text/csv');
                res.send(csv);
            });
        }).catch(function (err) {
            next(err);
        });
    });

Step 2: Database Logic
var xtrDatabaseConnection =require('./xtrDatabaseConnection').XTRDatabaseConnection;
       ReportData.prototype.getOverdueTrainings = async function (params) {
        var connection = new xtrDatabaseConnection();
        var sequelize = connection.getSequelize();
        try {
            var query = "CALL report_getOverdueTrainings(:p_CourseCode,:p_Revision,:p_RevisionNo,:p_UserGroup,:p_Username,:p_Status,:p_SortColoumnNo,:p_SortColoumnDirection,:p_callType,:p_StartIndex,:p_PageSize)";
            var replacements = {
                p_CourseCode: params.CourseCode,
                p_Revision: params.Revision,
                p_RevisionNo: (params.RevisionNo == '' || params.RevisionNo == null) ? 0 : params.RevisionNo,
                p_UserGroup: params.UserGroup,
                p_Username: params.Username,
                p_Status: params.Status,
                p_SortColoumnNo: params.SortColoumnNo,
                p_SortColoumnDirection: params.SortColoumnDirection,
                p_callType: params.callType,
                p_StartIndex: params.startIndex,
                p_PageSize: params.pageSize
            };
            //console.log(replacements);
            return await connection.executeQuerySequelize(sequelize, query, Sequelize.QueryTypes.RAW, replacements);
        } catch (e) {
            throw (e);
        } finally {
            //To close connections
            sequelize.connectionManager.close().then(() => console.log('Connection Closed'));
        }
    }




XTRDatabaseConnection.prototype.executeQuerySequelize = function (sequelize, query, queryType, replacements) {
    return sequelize.authenticate()
        .then(() => {
            return sequelize.query(query, {
                replacements: replacements,
                type: queryType
            }).
            then(result => result)
                .catch(err => {
                    throw (err);
                });
        })
        .catch(err => {
            xtrUtility.logErrorsToWinstonTransports('Unable to connect to the database or some error occurred while executing your query. ', err);
            throw new AppError(err, "dbError", "Unable to connect to the database or some error occurred while executing your query.");
        });
}

3 个答案:

答案 0 :(得分:1)

这是封锁:

    for (var i = 0; i < 100000; i++) { //Testing purpose
        for (var training of result) {
            overDueTrainings.push({
                'Over Due Trainings': training.OverDueTrainings
            })
        }
    }

直到执行结束。

 var result = reportManager.getOverdueTrainings(JSON.parse(req.params.criteria));
    result.then(function (result) {
 /****/
 return await connection.executeQuerySequelize(sequelize, query, Sequelize.QueryTypes.RAW, replacements);

答案 1 :(得分:1)

NodeJS是单线程,单个进程。只要javascript函数正在运行,其他任何东西都无法运行。这是设计的。只有在函数停止执行后,事件循环才会再次启动。

答案 2 :(得分:0)

Node.js正在开发单线程。因此,您需要将它用于具有异步调用的小型进程。当您使用async / await时,您将阻止回调函数。

因此您需要使用数据库函数作为承诺。它将工作异步。

.query('CALL someFunction()')
.then(function(response){
      //done
    }).error(function(err){
     //error
});

但是有一个问题。您需要加载21倍的结果。所以在这种情况下你需要使用递归函数。完成递归调用后,您可以将数据作为异步发送到客户端。