Бросать ошибки в NodeJS - UnhandledPromiseRejection - PullRequest
0 голосов
/ 31 марта 2020

Я довольно новичок в NodeJS и все еще пытаюсь понять, как обрабатывать ошибки. Я прочитал много вопросов, но я не понимаю, что я делаю неправильно.

Здесь у меня есть функция входа в систему:

export const login = async (req, res) => {
let body = req.body;

try {
  const user = await User.findOne({ username: body.username });

if (!user) {
  throw new InternalError("Username or password are wrong");
}

if (!bcrypt.compareSync(body.password, user.password)) {
  throw new InternalError("Username or password are wrong");
}

let token = jwt.sign({ data: user }, "secret", {
  expiresIn: 60 * 60 * 24 * 30
});

return res.json({
  user: user,
  token: token
 });
} catch (error) {
throw new GenericError(error);
 }
};

И это ошибка, которую я получаю, если, например, я ввел неправильный пароль:

(node:12332) UnhandledPromiseRejectionWarning: GenericError: Username or password are wrong
(node:12332) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by 
throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch()

Я знаю, что обещания, сделанные с помощью Await, должны иметь .then() и .catch(), но это не ошибка при выполнении обещания, а при проверке пароля , То, что я хочу, это выбросить ошибку и получить ответ. В данный момент запрос никогда не заканчивается, и отображается предыдущая ошибка.

Спасибо!

PS: InternalError и GenericError - это только ошибки, созданные мной, которые происходят от Error

1 Ответ

0 голосов
/ 31 марта 2020

Вы получаете предупреждение от узла, потому что вы повторно генерируете GenericError после перехвата InternalError. Вместо того, чтобы повторно выдавать GenericError, вы должны вернуть свой ответ или перехватить GenericError при вызове login.

Здесь ваш код изменен для обоих.

export const login = async (req, res) => {
  // We get the body info
  let body = req.body;

  try {
    // We find the user with the username from the body
    const user = await User.findOne({ username: body.username });

    // Let's assume no user exists, so we throw an InternalError,
    // This skips straight to the catch block.
    if (!user) {
      throw new InternalError("Username or password are wrong");
    }

    // We never reach these two statements
    // because of the error above being thrown.
    if (!bcrypt.compareSync(body.password, user.password)) {
      throw new InternalError("Username or password are wrong");
    }

    let token = jwt.sign({ data: user }, "secret", {
      expiresIn: 60 * 60 * 24 * 30
    });

   res.json({
      user: user,
      token: token
    });
  } catch (err) {
    // We caught our InternalError from not having a user above.
    // Now we should return a response that the user is invalid.
    // I am just going to return the error that we previously threw.
   res.json({
      error: err
    });
  }
};

Вы определенно можете бросить GenericError из вашего блока catch. Однако для этого требуется, чтобы вы перехватывали GenericError везде, где вы вызываете функцию входа в систему.

export const login = async (req, res) => {
  // We get the body info
  let body = req.body;

  try {
    // We find the user with the username from the body
    const user = await User.findOne({ username: body.username });

    // Let's assume no user exists, so we throw an InternalError,
    // This skips straight to the catch block.
    if (!user) {
      throw new InternalError("Username or password are wrong");
    }

    // We never reach these two statements
    // because of the error above being thrown.
    if (!bcrypt.compareSync(body.password, user.password)) {
      throw new InternalError("Username or password are wrong");
    }

    let token = jwt.sign({ data: user }, "secret", {
      expiresIn: 60 * 60 * 24 * 30
    });

   res.json({
      user: user,
      token: token
    });
  } catch (err) {
    // Throw the generic error
    throw GenericError(err);
  }
};


try {
  // We call the login function that is defined above.
  // It is going to throw a GenericError, so we have to
  // catch it.
  await login(req, res);
} catch (err) {
  // Now we need to catch the generic error
  res.json({
    error: err
  });
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...