简体   繁体   English

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

[英]Node.js Can't set headers after they are sent, res.json never called twice

Im working on a University project for a Economical Department. 我正在为经济部门从事大学项目。 I have many routes working correctly, but only this one creating a massive problem for me. 我有许多路线可以正常工作,但是只有这一条路线给我造成了很大的问题。

Whenever this route is done and the response is sent, I get the following error: 每当完成此路由并发送响应时,都会出现以下错误:

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)

The following is the function called by this route: 以下是此路由调用的函数:

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'});
        }
    }

I have no Idea why this is happening, even though res.json is never called twice. 我不知道为什么会这样,即使res.json从未被调用过两次。

A code like this is extremely hard to maintain: 这样的代码很难维护:

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

It doesn't even fit on the screen here so I'm having a hard time reading it. 它甚至不适合在这里显示在屏幕上,因此我很难阅读它。 I can give you some general advice on how to refactor it so it is manageable. 我可以就如何重构它提供一些一般性建议,以使其易于管理。 Hopefully this will help you fix this problem and also similar problems in the future. 希望这将帮助您解决此问题以及将来的类似问题。

First, take every single anonymous function and change it to a named function. 首先,获取每个匿名函数并将其更改为命名函数。 So, when you have: 因此,当您拥有:

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

Change it to: 更改为:

applicationModel.updateLastAppID(num, applicationType, updatedLastAppID);

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

Do it with every function that you have. 用您拥有的所有function来做。 This alone will probably show you your problem because you will have a nice self-documented code that is easy to read and understand, because: 仅此一项就可能显示您的问题,因为您将拥有一个易于阅读和理解的漂亮的自记录代码,原因是:

  • The functions will be named and also the errors will be easier to read 这些函数将被命名,并且错误将更易于阅读
  • Nothing will get indented so far that it's out of the screen 到目前为止,所有内容都不会缩进屏幕
  • You will be able to see at one function at a time 您将可以一次查看一项功能

For example this: 例如:

                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
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }
                });

will change to this: 将更改为:

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.

This is a first step but without it you will have a really hard time making sure that it all works. 这是第一步,但是如果没有它,您将很难确保所有步骤都能正常工作。

This is not hard, you can do it yourself step by step. 这并不难,您可以自己一步一步地做。 If you don't see the problem right away then you can post another question but with a code that is readable you will be much more likely to get answers. 如果您没有立即看到问题,则可以发布另一个问题,但是使用可读的代码,您更有可能获得答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM