Bookshelf/Passport:发送后无法设置headers

Bookshelf/Passport: Can't set headers after they are sent

我 运行 在路由的控制台中遇到了一些错误。快递路线如下:

router.get('/getInfo/:id', function(req, res, next) {
  return passport.authenticate('jwt', {session: false}, function(err, account, info) {
   if (err) { return next(err);}
   if (!account) { 
    new Account({_id: req.params.id}).fetch({columns: ['first_name']}).then(function(acc){ 
        return res.status(200).send(acc.toJSON());
    }); 
   }
   if(account._id != req.params.id) { 
    new Account({_id: req.params.id}).fetch({columns: ['first_name']}).then(function(acc){ 
        return res.status(200).send(acc.toJSON());
    });
   }
   else { 
    new Account({_id: req.params.id}).fetch().then(function(acc){ 
        return res.status(200).send(acc.toJSON());
    });
   }
  })(req, res, next);
});

只有在我未通过身份验证时才会出现错误消息 - 它说

Unhandled rejection Error: Can't set headers after they are sent.
...
at null.<anonymous> (/-----/routes/users.js:61:27)

第 61 行是 res.status(200).. 块中的 (account._id != req.params.id).

代码背后的想法是,如果您请求有关不是您的用户的信息(由 jwt 验证),您只会获得一些信息 - 现在只有 'first_name'。如果您请求有关您自己的信息,您会看到所有信息。

最让我烦恼的是,每次调用路由时我仍然得到有效响应。服务器没有 crash/refuses 加载/.. - 我得到的正是我所期望的。

我认为这是对承诺的不当使用

问题是当你写这个

if (!account) { 
    new Account({_id: req.params.id}).fetch({columns: ['first_name']}).then(function(acc){ 
        return res.status(200).send(acc.toJSON());
    }); 
   }

你实际上并没有从你的函数中 return 而是创建一个新帐户并得到承诺的执行 res.status(200)... 但你然后继续到下一行 if ... else ... 你也保证得到另一个 res.status(200)...

的承诺

所以你确实试图设置 headers 两次因此错误。

要解决这个问题,您有多种解决方案

(1) 您在 ifs

中的所有行中添加一个 ˋreturn`
router.get('/getInfo/:id', function(req, res, next) {
  return passport.authenticate('jwt', {session: false}, function(err, account, info) {
    if (err) { return next(err);}
    if (!account) { 
      return new Account({_id: req.params.id}).fetch({columns: ['first_name']}).then(function(acc){ 
        return res.status(200).send(acc.toJSON());
      }); 
    }
    if(account._id != req.params.id) { 
      return new Account({_id: req.params.id}).fetch({columns: ['first_name']}).then(function(acc){ 
        return res.status(200).send(acc.toJSON());
      });
    }
    else { 
      return new Account({_id: req.params.id}).fetch().then(function(acc){ 
        return res.status(200).send(acc.toJSON());
      });
    }
  })(req, res, next);
});

(2) 链接 ifs 以确保每次调用只执行一个 ifs

router.get('/getInfo/:id', function(req, res, next) {
  return passport.authenticate('jwt', {session: false}, function(err, account, info) {
    if (err) { return next(err);}
    if (!account) { 
      new Account({_id: req.params.id}).fetch({columns: ['first_name']}).then(function(acc){ 
        return res.status(200).send(acc.toJSON());
      }); 
    } else if(account._id != req.params.id) { 
      new Account({_id: req.params.id}).fetch({columns: ['first_name']}).then(function(acc){ 
        return res.status(200).send(acc.toJSON());
      });
    } else { 
      new Account({_id: req.params.id}).fetch().then(function(acc){ 
        return res.status(200).send(acc.toJSON());
      });
    }
  })(req, res, next);
});

(3) 或者您稍微重构一下代码,使其更符合 promises 的意图。实际上,您有 3 种不同的方式来创建帐户,但只有一种方式可以结束通话。我会更明确。那会给出类似

的东西
router.get('/getInfo/:id', function(req, res, next) {
  return passport.authenticate('jwt', {session: false}, function(err, account, info) {
    if (err) { return next(err);}
    let createAccountPromise;
    if (!account) { 
      createAccountPromise = new Account({_id: req.params.id}).fetch({columns: ['first_name']});
    } else if(account._id != req.params.id) { 
      createAccountPromise = new Account({_id: req.params.id}).fetch({columns: ['first_name']});
    } else { 
      createAccountPromise = new Account({_id: req.params.id}).fetch();
    }

    return createAccountPromise
      .then(function(acc){ 
        return res.status(200).send(acc.toJSON());
      }); 
  })(req, res, next);
});