2013-12-13 2 views
16

Я пытаюсь заполнить некоторые локальные данные, разрешая серию удаленных вызовов.
Когда каждое обещание разрешено, я загружаю данные и продолжаю.

Метод $q.all([]) делает именно это:

 $q.all([ 
      this.getUserInfo(11) 
       .then(function (r) { 
        results.push(r) 
       }), 

      this.getUserConns() 
       .then(function (r) { 
        results.push(r) 
       }), 

      this.getUserCtxs() 
       .then(function (r) { 
        results.push(r) 
       }) 
     ]) 
     .then(function() { 
      console.log(results) 
     }) 


Проблема в том, что этот код не упругим.
Если какой-либо из этих вызовов терпит неудачу, никто не получает рыбу!

Обертывание вызовы в Try/поймать заявления, просто вызывает $q.all() к полностью игнорировать запись, даже если не подведет (обратите внимание на console.log в FUNC) ...

 $q.all([ 
      this.getUserInfo2(11) 
       .then(function (r) { 
        results.push(r) 
       }), 

      function() { 
       try { 
        this.getUserGroups() 
         .then(function (r) { 
          console.log(r) 
          results.push(r) 
         }) 
       } 
       catch (err) { 
        console.log(err) 
       } 
      }, 
     ]) 
     .then(function() { 
      console.log(results) 
     }) 

Выход:

[Объект]


Любой намек на то, как я мог бы обернуть это, чтобы быть упругим?


Благодаря @dtabuenc, я пошел дальше. Реализация обратного вызова ошибки, я могу избежать разрыва цепи и нажать значения разрешенных обещаний.

Однако на консоли все еще отображается неприятное исключение ... Как я могу избавиться от этого, если я не могу попробовать/поймать асинхронные запросы?

код Caller

return $q.all([ 

      this.getUserInfo(user_id) 
       .then(function (r) { 
        results['personal_details'] = r 
       }), 

      this.getUserConns() 
       .then(
        function (r) { 
        results['connections'] = r 
        }, 
        function(err) { 
         console.log(err) 
        }) 

     ]) 
     .then(function() { 
      return (results) 
     }) 

код (впрыснуть вызванный метод с исключением)

getUserConns: function() { 

     return __doCall(ws.getUserConnections, {}) 
      .then(function(r) { 

       // very generic exception injected 
       throw new Error 

       if (r && r.data['return_code'] === 0) { 
        return r.data['entries'] 
       } 
       else { 
        console.log('unable to retrieve the activity - err: '+r.data['return_code']) 
        return null 
       } 
      }) 
    }, 

ответ

23

Это будет работать, но также приведет к ошибкам в массиве.

function push(r) { 
    results.push(r); 
} 

$q.all([ 
    this.getUserInfo(11).then(push).catch(push), 
    this.getUserConns().then(push).catch(push), 
    this.getUserCtxs().then(push).catch(push) 
]) 
.then(function() { 
    console.log(results); 
}) 

Вы также должны улучшить свое понимание обещаний, вы никогда не должны использовать try-catch с обещаниями - при использовании обещания, вы используете метод .catch() (все остальное неявным в try). Это работает как с обычными ошибками, так и с асинхронными ошибками.


Если вы хотите, чтобы полностью игнорировать ошибки:

function push(r) { 
    results.push(r); 
} 

function noop() {} 

$q.all([ 
    this.getUserInfo(11).then(push).catch(noop), 
    this.getUserConns().then(push).catch(noop), 
    this.getUserCtxs().then(push).catch(noop) 
]) 
.then(function() { 
    console.log(results); 
}) 
+0

На самом деле, я все еще новичок в Angular, обещаниях и даже JS, и я более чем счастлив каждый день изучать новые вещи! Метод .catch() по-прежнему не блокирует исключение, которое я порою в моем последнем примере, но я думаю, что это самое близкое, что я могу достичь своего идеального результата. Спасибо! – domokun

+1

@domokun угловые обещания неправильно сообщают даже пойманные исключения, нарушая дух обещаний/A +, если не нарушать спецификацию – Esailija

+0

Полезно знать ... Думаю ... Thx again! – domokun

0

я не уверен, что вы подразумеваете под упругими. Что вы хотите, если одно из обещаний не удастся?

Ваш try-catch не будет работать, потому что обещание будет асинхронно.

Однако вы можете передать обработчик ошибок в качестве второго параметра для вызова then() и делать все, что вы пожелаете.

+0

Хорошо, я забыл об обратном вызове ошибки. Он устойчив в том смысле, что цепь не прерывается, и это то, что я хотел. Однако я не могу скрыть исключение, если не поймаю его ... Я обновлю свой вопрос, чтобы объяснить – domokun

+0

Я не думаю, что вы можете уловить ошибки HTTP. Они всегда будут отображаться на консоли. Это независимо от того, используете вы угловатые или нет. – dtabuenc

+0

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

0

Тот же вопрос здесь. Для тех из вас, для петель: внутри затем ответ:

var tracks = []; 
var trackDfds = []; 
for(var i = 0; i < res.items.length; i++){ 
    var fn = function() { 
     var promise = API.tracks(userId, res.items[i].id); 
     return promise.then(function (res) { 
      if (res.items.length) { 
       tracks.push(res.items); 
      } 
     }).catch(angular.noop); 
    }; 
    trackDfds.push(fn()); 
} 
$q.all(trackDfds) 
    .then(function (res) { 
     console.log(tracks); 
    }); 
1

Я думаю, что это легче сделать:

$q.all([ 
mypromise1.$promise.catch(angular.noop), 
mypromise2.$promise.catch(angular.noop), 
mypromise1.$promise.catch(angular.noop) 
]) 
.then(function success(data) { 
//..... 
}); 
0

@ ответ Esailija, кажется, как обходной путь к проблеме. Не удается решить эту проблему за пределами основного источника, если у вас возникнут проблемы: $q.

Кажется немного мудрее иметь отклонения обратных вызовов для каждого then (2-й аргумент) и там, чтобы вставить $q.reject(...).

Пример:

$q.all([ 
    this.getUserInfo(11).then(
     function (response) { // UI data preparation for this part of the screen }, 
     function (response) { 
      $q.reject(response); 
     } 
    ), 
    // ... 
]) 
.then(
    function() { 
     // all good 
    }, 
    function() { 
     // at least one failed 
    } 
) 

Это особенно показан, когда модель пользовательского интерфейса зависит от всех вызовов Ajax.

Лично я считаю, что это безопасный способ действовать в любом случае, потому что в большинстве случаев вы хотите направить некоторые сообщения сервера на какой-то компонент тоста на обратные вызовы отклонения или каким-то образом оповестить пользователя (очередь 7 вызовов ajax не означает, что вы ничего не можете показать, потому что 1 не удалось - это означает, что вы не сможете показать какую-либо область экрана - для этого требуется специальная обратная связь с пользователем).

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