отклонение для обещания оболочки

#node.js #promise

#node.js #обещание

Вопрос:

Я подозреваю, что есть какая-то проблема с кодом, и это, скорее всего, в части catch, которая в целом приводит к сбою серверного приложения.

Цель: В основном проверка типа ошибки, которая может быть обработана, например, если объект не существует, для всех других ошибок корректно отклоните их обратно вызывающему без сбоя приложения.

 const Article = require("Article");

function upload(row) {
    return new Promise(function(resolve, reject){

        Article.requestData(row.schema) // if exists
            .then(Article.upload.bind(null, row.article)) //may throw error
            .then(resolve) // done if OK
            .catch(function(error){
                if(error.code == "NotFoundException") { // entity doesn't exists
                    Article.create(row.schema) // create entity
                        .then(Article.upload.bind(null, row.article)) // upload
                        .then(resolve, reject); // reject upload error
                } else { // upload errors
                    // reject(error); // tried reject
                    throw error; // trying re-throw
                }
            });
    });
}
  

Код сначала пытается получить информацию о сущности, и если она не найдена, он создает ее.

Теперь часть загрузки может выдавать ошибку, которую мне нужно корректно отправить обратно вызывающему.

Ошибка, которую я получаю, это UnhandledPromiseRejectionWarning

Ответ №1:

Тот же код, но переписанный.

 function upload(row) {

   return Article.requestData(row.schema) // if exists
     .then(Article.upload.bind(null, row.article)) //may throw error
     .catch(function(error){
        if(error.code == "NotFoundException") { // entity doesn't exists
           return Article.create(row.schema) // create entity
             .then(Article.upload.bind(null, row.article)) // upload
        } else {
            throw error;
     });
}
  

Запуск new Promise() часто называют антишаблоном. Иногда вы не можете легко обойти это, но это типичный случай, когда это совершенно не нужно.

Каждый раз, когда вы вызываете .then() or .catch() , возвращается новое обещание, и это то же самое обещание, которое вы хотите вернуть из своей функции.

Вот версия async / await, просто для удовольствия:

 async function upload(row) {

  try {
    await Article.requestData(row.schema) // if exists
    await Article.upload.bind(row.article);
  } catch (error) {

    if(error.code == "NotFoundException") { // entity doesn't exists
       await Article.create(row.schema) // create entity
       await Article.upload(row.article);
    } else {
       throw error;
    }
  }
}
  

Комментарии:

1. спасибо за переписывание, но это не то, что я ищу, причина и решение, почему предложение else терпит неудачу, несмотря на антишаблон, не могли бы вы, пожалуйста, осветить реальную проблему.

2. есть ли проблема с вызовом reject в разделе catch?

3. @Разработчик одна из основных ошибок заключается в том, что вы не возвращаетесь из нескольких ваших цепочек обещаний, что означает, что если в них возникают ошибки, они «проглатываются» и никогда не обрабатываются. Все ваши цепочки обещаний должны возвращать свой результат обратно (как обещание) в основную функцию. Мой ответ — самое разумное решение для этого, но если вы хотите сохранить свою версию для спагетти, убедитесь, что вы также улавливаете ошибки из вашей второй цепочки обещаний.

4. Обратите внимание, что в моей версии каждый раз, когда я запускаю цепочку обещаний, я возвращаю ее. (Article.requesData и article.upload). Но перенастройка в вашем случае ничего не даст из-за использования new Promise, поэтому ваш единственный вариант — добавить catch предложения к каждому и молиться, чтобы в ваших заключительных предложениях catch не возникло ошибки

5. one major mistake is that you are not returning from several of your promise-chains это ценно. Теперь я понимаю антипаттерн, и, к счастью, у меня есть правильный подход с вашей стороны, но просто чтобы понять и устранить проблему, что бы вы сделали, чтобы исправить мою версию так, как она есть, с обещанием оболочки. Это поможет мне лучше понять. Пожалуйста, предоставьте кодовое решение в другой правке под вашим данным ответом. Еще раз спасибо.