В чем разница между броском внутрь ?затем заблокировать или внутри асинхронного блока ожидания?

#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 функция фактически вернула обещание, которое было немедленно выполнено… таким образом, он никогда не ожидал запроса к базе данных.