Node.js发送后无法设置标头,res.json从未调用过两次

时间:2016-11-16 22:16:46

标签: javascript json node.js express

我正在为一个经济部门的大学项目工作。我有很多路线正常工作,但只有这个路线给我造成了很大的问题。

无论何时完成此路由并发送响应,我都会收到以下错误:

Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)
at ServerResponse.header (/Users/Nasseralwan/Documents/CustExumpSDP/CustomExemptionSystem/node_modules/express/lib/response.js:719:10)
at ServerResponse.send (/Users/Nasseralwan/Documents/CustExumpSDP/CustomExemptionSystem/node_modules/express/lib/response.js:164:12)
at ServerResponse.json (/Users/Nasseralwan/Documents/CustExumpSDP/CustomExemptionSystem/node_modules/express/lib/response.js:250:15)
at /Users/Nasseralwan/Documents/CustExumpSDP/CustomExemptionSystem/controllers/application.js:171:56
at Query._callback (/Users/Nasseralwan/Documents/CustExumpSDP/CustomExemptionSystem/models/application.js:141:25)
at Query.Sequence.end (/Users/Nasseralwan/Documents/CustExumpSDP/CustomExemptionSystem/node_modules/mysql/lib/protocol/sequences/Sequence.js:85:24)
at Query._handleFinalResultPacket (/Users/Nasseralwan/Documents/CustExumpSDP/CustomExemptionSystem/node_modules/mysql/lib/protocol/sequences/Query.js:144:8)
at Query.OkPacket (/Users/Nasseralwan/Documents/CustExumpSDP/CustomExemptionSystem/node_modules/mysql/lib/protocol/sequences/Query.js:78:10)
at Protocol._parsePacket (/Users/Nasseralwan/Documents/CustExumpSDP/CustomExemptionSystem/node_modules/mysql/lib/protocol/Protocol.js:280:23)

以下是此路线调用的功能:

registerFactory: function (req, res ) {
        var userDetails = req.user;
        var requestData = req.body;
        var hscode = "NULL";
        var applicationID = "FR";
        var applicationType = "Factory";
        var factoryId = "";
        if (userDetails.usergroup == "Client") {
            var d = new Date();
            var year = d.getFullYear();
            applicationID = applicationID + year;
            var dnum = 5;
            var num = 0;
            applicationModel.getLastAppID(applicationType, function (err, results) {
                if (err) {
                    return res.json({success: false, message: 'Database Error. '});
                }else{
                    num = results[0].LastID;
                    console.log(num);
                    dnum = dnum - num.toString().length;
                    while (dnum != 0) {
                        applicationID = applicationID + "0";
                        dnum = dnum - 1;
                    }
                    applicationID = applicationID + num;
                    num = num + 1;
                    applicationModel.updateLastAppID(num, applicationType, function (err) {
                        if (err) {
                            return res.json({success: false, message: 'Database Error. '});
                        }else{
                            factoryController.registerFactory(userDetails,requestData, function (err,FID) {
                                if (err) {
                                    return res.json({success: false, message: 'Database Error. '});
                                }else{
                                    factoryId =  FID;
                                    applicationModel.createFactoryRegApplication(userDetails, requestData, applicationType, applicationID,hscode, function (err) {
                                        if (err) {
                                            return res.json({success: false, message: 'Database Error. '});
                                        } else {
                                            res.json({
                                                success: true,
                                                message: 'Application Created',
                                                data: {RequestID: applicationID,
                                                    FactoryID : factoryId
                                                }
                                            });
                                        }
                                    });
                                }
                            });

                        }
                    });
                }
            });
        } else {
            return res.json({success: false, message: 'unauthorized Access'});
        }
    }

我不知道为什么会发生这种情况,即使res.json永远不会被调用两次。

1 个答案:

答案 0 :(得分:3)

这样的代码非常难以维护:

http://icompile.eladkarako.com/wp-content/uploads/2016/01/icompile.eladkarako.com_callback_hell.gif

它甚至不适合在屏幕上显示,所以我很难阅读它。我可以给你一些关于如何重构它以使其易于管理的一般性建议。希望这将有助于您解决此问题以及将来类似的问题。

首先,取每个匿名函数并将其更改为命名函数。所以,当你有:

applicationModel.updateLastAppID(num, applicationType, function (err) {
  // ...
});

将其更改为:

applicationModel.updateLastAppID(num, applicationType, updatedLastAppID);

function updatedLastAppID(err) {
  // ...
}

使用您拥有的每个function执行此操作。仅此一项可能会向您展示您的问题,因为您将拥有一个易于阅读和理解的自编档文,因为:

  • 将命名函数,并且错误将更容易阅读
  • 到目前为止,什么都不会缩进,以至于它不在屏幕之外
  • 您将能够一次看到一个功能

例如:

                applicationModel.updateLastAppID(num, applicationType, function (err) {
                    if (err) {
                        return res.json({success: false, message: 'Database Error. '});
                    }else{
                        factoryController.registerFactory(userDetails,requestData, function (err,FID) {
                            if (err) {
                                return res.json({success: false, message: 'Database Error. '});
                            }else{
                                factoryId =  FID;
                                applicationModel.createFactoryRegApplication(userDetails, requestData, applicationType, applicationID,hscode, function (err) {
                                    if (err) {
                                        return res.json({success: false, message: 'Database Error. '});
                                    } else {
                                        res.json({
                                            success: true,
                                            message: 'Application Created',
                                            data: {RequestID: applicationID,
                                                FactoryID : factoryId
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }
                });

将改为:

applicationModel.updateLastAppID(num, applicationType, updatedID);

function updatedID(err) {
  if (err) {
    return res.json({success: false, message: 'Database Error. '});
  } else {
    factoryController.registerFactory(userDetails, requestData, factoryRegistered);
  }
}
// etc.

这是第一步,但如果没有它,你将很难确保一切正常。

这并不难,你可以自己一步一步做。如果您没有立即看到问题,那么您可以发布另一个问题,但使用可读的代码,您将更有可能获得答案。