Node.js error: 'Can't set headers after they are sent' on post

Node.js error: 'Can't set headers after they are sent' on post

好的,这个话题在 Whosebug 上已经回答了很多次,但我没有找到对我有用的东西。

我已经设置了一个 nodejs 服务器,'get' 查询工作正常,但是当我尝试 post 时,我得到了这个错误,它被写成 'Cannot post /fr/login'(url 是域。com/fr/login)

如你所知,我使用 Express、i18n 和 Nunjucks 作为模板引擎。

真不知道怎么回事。我正在尝试制作一个登录系统,但这阻止了我这样做。 Sa bassically 发生了什么,是用户输入它的信息然后我用邮件和密码调用 User.findOne 然后它应该触发回调并发生错误(成功登录被认为是错误)。目前对用户信息的回调是回调和'transfer'。 (您可能会在回调中看到 console.log,它正在工作)。但是当它触发 res.render 时,我得到了两个错误。

这是我的文件:

  1. server.js

    app.post('/:lang/login', getChangelog, getAlert, function(req, res) { 
    
      i18n.setLocale(req, req.params.lang);
        let version;
        if(req.cookies.version) {
           version = req.cookies.version;
        }
        if(!version) version = 0;
    
        var email = req.body.mailconnect;
        var password = req.body.mdpconnect;
    
        User.findOne({ email: email, password: password }, function(err, user){
          if(user['error'] != "LOGIN OK") {
            console.log(user);
            errorInfo['showError'] = true;
            errorInfo['error-msg'] = req.__("Error-WrongMail");
            res.render('login/login.njk', { title: req.__('Login-PageTitle'), 
    style: 'login.css', alertInfo: alertInfo, errorInfo: errorInfo, version: version, currVersion: currVersion, firstVersion: firstVersion, changelog: changelog });
          } else {
            var hash = user["mdp"];
            hash = hash.replace(/^$2y(.+)$/i, 'a');
            bcrypt.compare(password, hash, function(err, res2) {
              if(res2){
                errorInfo['showError'] = false;
                errorInfo['error-msg'] = "LOGIN OK";
    
                res.redirect(i18n.getLocale + '/agent/' + user["id"] + '/selectservice');
              } else{
                errorInfo['showError'] = true;
                errorInfo['error-msg'] = req.__("Error-MailAndPassNoMatch");
                res.render('login/login.njk', { title: req.__('Login-PageTitle'), style: 'login.css', alertInfo: alertInfo, errorInfo: errorInfo, version: version, currVersion: currVersion, firstVersion: firstVersion, changelog: changelog });
              }
            });
          }
        });
      });
    
  2. user.js

    var db = require('../other/mysql.js');
    exports.findOne = (data, callback) => {
    if(data.email != "" && data.password != "") {
      db.connection.query('SELECT * FROM membres WHERE mail = ?', data.email)
       .on('result', function (row) {
    
         let user = new Object();
         user = row;
         user['error'] = 'WrongMail'; //Temporary, just for testing
    
         callback(null, user);
    
       })
       .on('error', function (err) {
         let user = new Object();
         user['error'] = 'SQL';
         callback(err, user});
      });
     }
    }
    
  3. mysql.js

    var mysql = require('mysql');
    
    var pool = mysql.createPool({
      connectionLimit : 10,
      host: "ip",
      user: "user",
      password: "password",
      database: "databse"
    });
    
    exports.connection = {
        query: function () {
            var queryArgs = Array.prototype.slice.call(arguments),
                events = [],
                eventNameIndex = {};
    
    pool.getConnection(function (err, conn) {
        if (err) {
            if (eventNameIndex.error) {
                eventNameIndex.error();
            }
        }
        if (conn) { 
            var q = conn.query.apply(conn, queryArgs);
            q.on('end', function () {
                conn.release();
            });
    
            events.forEach(function (args) {
                q.on.apply(q, args);
            });
        }
    });
    
    return {
        on: function (eventName, callback) {
            events.push(Array.prototype.slice.call(arguments));
            eventNameIndex[eventName] = callback;
            return this;
        }
    };
    }
    };
    
  4. 这是我的 nodejs 日志

    RowDataPacket {
       id: 1,
       mail: 'mymail',
    
    
        matricule: '972',
        mdp: 'an hashed password',
        num_vehicle: 8001,
        profession: 'agent',
        dispatch: 'Y',
        supervisor: 'Y',
        admin: 'Y',
        status: 1,
        tkn: '3faixj17guocz89zfdx5a9',
        serv: '',
        error: 'WrongMail' }
    
    
        Caught exception:  Error: Can't set headers after they are sent.
           at validateHeader (_http_outgoing.js:491:11)
           at ServerResponse.setHeader (_http_outgoing.js:498:3)
           at ServerResponse.header (F:\GitHub\terminal.ga\node_modules\express\lib\response.js:730:10)
           at ServerResponse.send (F:\GitHub\terminal.ga\node_modules\express\lib\response.js:170:12)
    at done (F:\GitHub\terminal.ga\node_modules\express\lib\response.js:967:10)
    at F:\GitHub\terminal.ga\node_modules\nunjucks\src\environment.js:37:5
    at RawTask.call (F:\GitHub\terminal.ga\node_modules\asap\asap.js:40:19)
    at flush (F:\GitHub\terminal.ga\node_modules\asap\raw.js:50:29)
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)
    

同样的问题我遇到了很多times.For我这个错误发生了两次:

  1. 当我发送响应多于一回调时
  2. 当我无法在回调中设置正确的查询结果条件以在获取结果后执行其他语句时

你能 post 也 app.js 只用那个路由调用 @Willbill360

我发现了我的问题所在。查询返回结果的时间超过了时间,因此它多次调用回调。

为了解决这个问题,我创建了一个新的导出,它只从池中获取连接并执行查询,就像在文档中一样。一种确保它不会多次发送数据的非常简单的方法。