O que acontece com $ q.all () quando algumas chamadas funcionam e outras falham?

O que acontece com $ q.all () quando algumas chamadas funcionam e outras falham?

Eu tenho o seguinte código:

var entityIdColumn = $scope.entityType.toLowerCase() + 'Id'; var requests = $scope.grid.data .filter(function (rowData, i) { return !angular.equals(rowData, $scope.grid.backup[i]); }) .map(function (rowData, i) { var entityId = rowData[entityIdColumn]; return $http.put('/api/' + $scope.entityType + '/' + entityId, rowData); }); $q.all(requests).then(function (allResponses) { //if all the requests succeeded, this will be called, and $q.all will get an //array of all their responses. console.log(allResponses[0].data); }, function (error) { //This will be called if $q.all finds any of the requests erroring. var abc = error; var def = 99; }); 

Quando todas as chamadas $ http funcionam, a matriz allResponses é preenchida com dados.

Quando um falhar, entendo que a segunda function será chamada e a variável de erro, dada os detalhes.

No entanto, alguém pode me ajudar a explicar o que acontece se algumas das respostas funcionam e outras falham?

Eu acredito que desde que a biblioteca de promises é baseada na implementação Q , assim que a primeira promise é rejeitada, o callback de rejeição é chamado com o erro. Não espera que outras promises sejam resolvidas. Veja a documentação do Q https://github.com/kriskowal/q . Para Q.all isso é o que é mencionado

A function all retorna uma promise para uma matriz de valores. Quando esta promise é cumprida, a matriz contém os valores de cumprimento das promises originais, na mesma ordem que essas promises. Se uma das promises dadas for rejeitada, a promise devolvida é imediatamente rejeitada, não aguardando o restante do lote.

Já faz um tempo que essa pergunta foi postada, mas talvez minha resposta ainda possa ajudar alguém. Eu resolvi um problema semelhante no meu fim simplesmente resolvendo todas as promises, mas com um retorno eu poderia processar mais tarde e ver se havia algum erro. Aqui está o meu exemplo usado para pré-carregar alguns resources de imagem:

 var loadImg = function(imageSrc) { var deferred = $q.defer(); var img = new Image(); img.onload = function() { deferred.resolve({ success: true, imgUrl: imageSrc }); }; img.onerror = img.onabort = function() { deferred.resolve({ success: false, imgUrl: imageSrc }); }; img.src = imageSrc; return deferred.promise; } 

Mais tarde, posso ver quais são erradas:

 var promiseList = []; for (var i = 0; i < myImageList.length; i++) { promiseList[i] = loadImg(myImageList[i]); } $q.all(promiseList).then( function(results) { for (var i = 0; i < results.length; i++) { if (!results[i].success) { // these are errors } } } ); 

Edit: Apenas suportado em Q de Kris Kowal – mas ainda um petisco útil

Se você quiser processar todos eles sem rejeitar imediatamente em caso de falha use allSettled

Veja o que os documentos dizem:

Se você quiser esperar que todas as promises sejam cumpridas ou rejeitadas, você pode usar allSettled.

 Q.allSettled(promises) .then(function (results) { results.forEach(function (result) { if (result.state === "fulfilled") { var value = result.value; } else { var reason = result.reason; } }); }); 

Aqui está uma pequena resposta para isso. Neste violino você pode ver como funciona, se ocorrer um erro em alguma promise.

 $q.all([test1(), test2()]).then(function() { // success }, function() { // error }); 

http://jsfiddle.net/wd9w0ja4/

Eu encontrei um novo pacote angular que adiciona a funcionalidade allSettled a $ q em angular:

https://github.com/ohjames/angular-promise-extras

No meu caso, eu precisava saber quando a última promise foi resolvida, não importa se foi bem-sucedida ou não. $ q.all não era uma opção, porque se falhar, cai imediatamente. Eu precisava disso para garantir que o usuário fosse redirecionado não importando o que acontecesse, mas apenas se todos os dados fossem processados ​​(ou não) para que pudessem ser carregados na próxima página. Então acabei com isso:

  1. Cada promise / chamada implementada também falha o retorno de chamada em que a function “redirecionamento” é chamada em callbacks de sucesso e de falha.
  2. Neste contador de funções está definido, o que é aumentado com cada chamada. Se isso atingir o número de promises / chamadas, o redirecionamento para a próxima exibição é feito.

Eu sei que é uma maneira muito ruim de fazer isso, mas funcionou para mim.

Você não poderia simplesmente lidar com a condição de erro em suas promises $ http antes de passá-las para $ q? Promessas são acorrentadas, então isso deve funcionar:

 return $http.put('/api/' + $scope.entityType + '/' + entityId, rowData).then(function(r){return r;}, angular.noop); 

Obviamente, você pode alterar o noop em qualquer transformação desejada, mas isso evita a rejeição que impede que o $q.all .

Intereting Posts