MEAN Stack - невозможно установить заголовки после их отправки клиенту - PullRequest
1 голос
/ 11 февраля 2020

Это сводит меня с ума. Приложение, над которым я работаю, выдает ошибку «Невозможно установить заголовки после их отправки клиенту». Я очень новичок в написании чего-либо на сервере и не могу понять, почему это происходит. Я прочитал все соответствующие посты по этому вопросу, и все еще не вижу, что не так. Пожалуйста, помогите мне найти то, что мне не хватает.

Это маршрут, к которому я пытаюсь получить доступ, userRoutes. js:

router.post('/login', (req, res, next) => {
  console.log('1');
  let fetchedUser;
  HaulerUser.findOne({ username: req.body.username })
    .then(user => {
      console.log('2');
      if (!user) {
        return res.status(401).json({
          message: 'Auth failed'
        });
      }
      console.log('3');
      fetchedUser = user;
      return bcrypt.compare(req.body.password, user.password);
    })
    .then(result => {
      console.log('4');
      if(!result) {
        return res.status(401).json({
          message: 'Auth failed'
        });
      }
      const token = jwt.sign(
        { username: fetchedUser.username, userId: fetchedUser._id },
        'secret_this_should_be_longer',
        { expiresIn: '1hr' }
      );
      console.log('5');
      res.status(200).json({
        token: token,
        expiresIn: 3600,
        userId: fetchedUser._id
      });
      console.log('6');
    })
    .catch(err => {
      console.log('7');
      return res.status(401).json({
        message: 'Invalid authentication credentials',
        error: err
      });
    });
});

Кроме того, это только печать 1, 2 , 4 и 7 к консоли ????

Это основной NodeJS код.

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader(
    'Access-Control-Allow-Headers',
    'Origin, X-Requested-With, Content-Type, Accept, Authorization');
  res.setHeader(
    'Access-Control-Allow-Methods',
    'GET, POST, PATCH, PUT, DELETE, OPTIONS'
  );
  next();
});

app.use('/api/user', userRoutes);
app.use('/api/manifests', manifestsRoutes);
app.use('/api/sites', sitesRoutes);

Я немного над головой с этим ... Я уверен, что это что-то маленькое ... пожалуйста, помогите .....

1 Ответ

1 голос
/ 11 февраля 2020

Как уже упоминалось в комментариях, вы звоните res.json() более одного раза, о чем и говорит ошибка.

Вы сталкиваетесь с общей проблемой, с которой сталкиваются люди, когда учатся связывать обещания , Возвращение res.status(401).json({...}) не отклоняет Обещание и вместо этого возвращает результат res.status(401).json({...}) в следующий блок .then(), который, в свою очередь, делает то же самое в стеке, когда пользователь не найден.

У вас есть Есть несколько вариантов, чтобы исправить это, но самый распространенный способ - использовать исключения для выхода из цепочки обещаний. Вместо res.status(401).json({...}) в каждом if блоке выполните throw new Error('{an error message}'). Это выйдет из цепочки и перейдет к вашему .catch(), который затем отправляет вызовы res.status(401).json({...}). Затем вы можете также записать сообщение об ошибке speci c при возврате вызывающему сообщению generi c.

router.post('/login', (req, res, next) => {
  console.log('1');
  let fetchedUser;
  HaulerUser.findOne({ username: req.body.username })
    .then(user => {
      console.log('2');
      if (!user) {
        throw new Error(`User '${req.body.username}' not found`);
      }
      console.log('3');
      fetchedUser = user;
      return bcrypt.compare(req.body.password, user.password);
    })
    .then(result => {
      console.log('4');
      if(!result) {
        throw new Error(`Password did not match`);
      }
      const token = jwt.sign(
        { username: fetchedUser.username, userId: fetchedUser._id },
        'secret_this_should_be_longer',
        { expiresIn: '1hr' }
      );
      console.log('5');
      res.status(200).json({
        token: token,
        expiresIn: 3600,
        userId: fetchedUser._id
      });
      console.log('6');
    })
    .catch(err => {
      console.log('7');
      console.log(err);
      res.status(401).json({ // You don't need a return here
        message: 'Invalid authentication credentials',
        error: err
      });
    });
});

Если вы находитесь на узле 8 или выше, вы можете использовать async / await вместо .then() / .catch() и ваш код будет вести себя так, как вы ожидали.

...