2014-10-29 2 views
-3

У меня есть следующий метод:Лучшая практика для обработки исключений при использовании Q.promise

module.exports.getId = function(someObject) { 

    var myId = null; 

    return Q.Promise(function(resolve, reject, notify) { 

     // Loop through all the id's 
     someObject.user.player._id.forEach(function (id) { 

      if (id.root == "1.2.3.4.5.6") { 
       myId = id.extension; 
      } 
     }); 

     resolve(myId); 
    }); 
}; 

Этот метод отлично работает до тех пор, как someObject существует и имеет атрибуты user.player._id.

Проблема, с которой я сталкиваюсь, заключается в том, что если someObject имеет значение null или не имеет всех соответствующих вложенных атрибутов, генерируется исключение, и обещание никогда не будет разрешено. Единственный способ, которым я действительно вижу исключение, - это если у меня есть .fail на вызывающей функции, но это все еще фактически не разрешает обещание.

Пример того, как я в настоящее время можно увидеть исключение:

myLib.getId.then(function() { 
    // something 
}).fail(function(err) { 
    console.log(err); 
}); 

Я знаю 2 способа обойти эту проблему, но я не уверен, если либо это лучший способ справиться с этим что-то вроде ,

Вариант 1 (использование попытка/поймать в моем Q.promise):

module.exports.getId = function(someObject) { 

    var myId = null; 

    return Q.Promise(function(resolve, reject, notify) { 

     try { 
     // Loop through all the id's 
     someObject.user.player._id.forEach(function (id) { 

      if (id.root == "1.2.3.4.5.6") { 
       myId = id.extension; 
      } 
     }); 

     } catch(e) { 
     reject(e); 
     } 

     resolve(myId); 
    }); 
}; 

Вариант 2 (явно проверить, если someObject.user.player._id существует):

module.exports.getId = function(someObject) { 

    var myId = null; 

    return Q.Promise(function(resolve, reject, notify) { 

     ifi(someObject.user.player._id exists..) { 

     // Loop through all the id's 
     someObject.user.player._id.forEach(function (id) { 

      if (id.root == "1.2.3.4.5.6") { 
       myId = id.extension; 
      } 
     }); 

     resolve(myId); 
     } else { 
     reject('invalid object'); 
     } 
    }); 
}; 

Вариант 1 кажется мне неприятным, потому что я использую try/catch внутри обещания. Вариант 2 решает мою проблему, но любые другие неожиданные исключения не поймаются.

Есть ли лучший способ справиться с этим?

+0

Не нисходящий, но мне интересно - почему вы используете обещание в синхронном коде для начала? Также - если вы используете обещание, бросок и отклонение - это одно и то же. –

+0

Я использую обещание в синхронном коде b/c, это часть библиотеки, и я не хочу, чтобы пользователь должен был знать, какие методы в lib синхронны, а какие нет, поэтому я сделал их все async. Я знаю, что бросок и отказ - то же самое. Я на самом деле ничего не бросаю. – Catfish

+1

Уверен, что вы - когда вы делаете 'a.b.c ...', не зная, что там вы пишете код, который может быть брошен так, что 'rejext' после улова в лучшем случае избыточен. –

ответ

-1

Ваш первый пример имеет несколько проблем:

  • Когда вы ловите исключение, вы опровергали обещание, то разрешения обещание. Это нарушает договор о обещании; Вы можете обойти это, вызвав решение в пределах try, а не снаружи.
  • С помощью try/catch вы можете проглотить непреднамеренные ошибки. То есть вы предполагаете, что единственная ошибка исходит от someObject.user.player._id, которая не существует. На данный момент это может быть правдой, но не гарантируется, что ваш код изменится.

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

+0

@downvoter Пожалуйста, объясните downvotes, чтобы я мог удалить/улучшить ответ. –

+1

Не я, но я не вижу, как это затрагивает вопрос, кроме «это мое мнение, что такие-то» –

+0

Downvoting trolls здесь сегодня – Catfish

Смежные вопросы