#javascript #node.js #ecmascript-6 #es6-promise
#javascript #node.js #ecmascript-6 #es6-обещание
Вопрос:
Я получаю эту ошибку:
(node:9868) UnhandledPromiseRejectionWarning: #<Object>
(node:9868) 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(). (rejection id: 1)
(node:9868) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code
Я оборачиваю метод create с помощью экспресс-обработчика ошибок, который выглядит следующим образом:
export const errorHandler = (callback: any) => {
return (req: Request, res: Response, next: NextFunction) => {
callback(req, res, next).catch(next);
};
};
когда я пытаюсь это сделать:
async create(entity: T){
this._model
.findOne({ name: (entity as any).name })
.then((res) => {
if (res) {
throw Exceptions.ENTITY_EXISTS; // doesnt work
}
})
}
однако, когда я меняю его на async await, он работает нормально
async create(entity: T) {
const res = await this._model.findOne({ name: (entity as any).name });
if (res) throw Exceptions.ENTITY_EXISTS;
}
Также, когда я попытался сделать вместо throw Promise.reject(Exceptions.ENTITY_EXISTS)
, он выдал ту же ошибку.
Может ли кто-нибудь объяснить мне различия между этими тремя, а также почему работает только асинхронное ожидание?
Ответ №1:
Разница действительно в том, где throw
это происходит. В рабочей версии это делает обещание, возвращенное create()
to settle, отклоненным.
В нерабочей версии обещание, возвращенное .then()
to settle, считается отклоненным. Однако это обещание не является тем, которое возвращается create()
, и поэтому, даже если вы правильно обработаете отклонение в create()
… это не обрабатывает отклонение, которое произошло в then()
обещании. Они не подключены, и поэтому вы не обрабатываете это отклонение.
Чтобы исправить первую версию, обязательно верните обещание, возвращенное .then()
:
create(entity: T){
return this._model
// ^^^^^^
.findOne({ name: (entity as any).name })
.then((res) => {
if (res) {
throw Exceptions.ENTITY_EXISTS; // doesnt work
}
});
}
Примечание: Хотя вы могли бы сохранить async
перед функцией, это действительно не так полезно, если вы не используете await
и не возвращаете обещание.
NB2: Из-за этого отсутствия return
create
функция фактически вернула обещание, которое было немедленно выполнено… таким образом, он никогда не ожидал запроса к базе данных.