Biorąc pod uwagę następujące dwa {X0}} Przykłady:

var exampleOne = $resource('/path').save(objectOne);
exampleOne.$promise.then(function (success) {}, function (error) {});

var exampleTwo = $resource('/path').save(objectTwo);
exampleTwo.$promise.then(function (success) {});

[UWAGA: Przykład Dwa nie zawiera żadnego procedury obsługi błędów]

I przechwytywnik, który znajduje się poniżej wszystkich $http żądania:

var interceptor = ['$location', '$q', function ($location, $q) {
   function error(response) {
       if (response.status === 400) {
           return $q.reject(response);
       }
       else {
           $location.path('/error/page');
       }
       return $q.reject(response);
   }

   return {
       'responseError': error
   };
}

$httpProvider.interceptors.push(interceptor);

Jak mogę dokonać przechwytującego nie odrzucenia, gdy przykładowe zasoby $promise.then() nie zawierają zwrotu pieniędzy? Jeśli oddzwonienie istnieje jak w exampleOne, chcę odrzucić, ale jeśli nie tak, jak w exampleTwo, chcę przekierować na stronę błędu, w ten sposób zmieniając warunkową do czegoś, co:

if (response.status === 400 && $q.unresolvedPromises.doIndeedExist()) { ...

Dlaczego? Ponieważ tylko niektóre sytuacje w moim projekcie wezwają obsługę 400 w sposób przyjazny dla użytkownika, a zatem chciałbym wyeliminować wiele duplikowanych wyłączania zwrotów błędów lub konieczności umieszczenia listy niezwykłych sytuacji w Interceptor. Chciałbym, aby interceptor mógł zdecydować się na obecności innego przewodnika w łańcuchu obietnicy.

6
Mike Trionfo 13 sierpień 2014, 22:54

2 odpowiedzi

Najlepsza odpowiedź

Po prostu umieścić to niemożliwe , nie możesz wykryć, czy ktoś przyłączy przewóz w pewnym momencie w przyszłości, tak jak nie możesz powiedzieć, czy kiedy jesteś throw w funkcji, będzie być złapanym na zewnątrz lub nie. Jednak co chcesz zrobić, można zrobić .

To nie jest pytanie "noob" i jest bardzo fundamentalne:

 function foo()
    throw new Error(); // I want to know if whoever is calling `foo`
                       // handles this error
 }

Po pierwsze, co możesz zrobić

Wystarczy umieścić w pierwszym przypadku:

 exampleOne.$promise.then(function (success) {}, function (error) {});

Co dostajesz obietnicę, która jest zawsze spełniona. Jednak w drugim przypadku obietnica może zostać odrzucona. Obsługa odrzucenia z przewodnikiem odrzucenia jest jak catch w prawdziwym kodzie - po poradzonym sobie z nim nie jest już odrzucony.

Osobiście nie użyłem tu interceptora, ale raczej wzorzec przy użyciu zasobów, ponieważ jest to bardziej jasne z intencją, można owinąć go w funkcji, więc nie będzie potrzebny zakres, ale lubię ten pomysł mniej. Oto, co zrobiłbym

attempt(function(){
    return $resource('/path').save(objectTwo).$promise.
           then(function (success) {});
});

function attempt(fn){
    var res = fn();
    res.catch(function(err){
        // figure out what conditions you want here
        // if the promise is rejected. In your case check for http errors
        showModalScreen();
    }
    return res; // for chaining, catch handlers can still be added in the future, so
                // this only detects `catch` on the function passed directly so 
                // we keep composability
}

Teraz krótki dowód, że nie można tego zrobić

Udowodnijmy to dla zabawy.

Powiedzmy, że otrzymujemy kod programu M, tworzymy nową obietnicę p i zastąpić instrukcję return w m i throw instrukcja w M z return p.catch(function(){}) i Dodaj również return p.catch(function(){}), teraz jest dodawany do p, jeśli i tylko wtedy, gdy się kończy M. Tak więc w krótkim - podanym kodzie M zbudowaliśmy sposób, aby sprawdzić, czy zatrzymuje się na podstawie istnienia rozwiązania problemu znalezienia, jeśli {x7}} jest dołączony do p - więc ten problem jest przynajmniej Tak mocno jak Problem zatrzymujący.

2
Benjamin Gruenbaum 13 sierpień 2014, 20:56

Być może możesz odroczyć przekierowanie za pomocą limitu czasu zerowego i daj szansę na błąd, jeśli każdy istnieje, aby ustawić flagę na obiekcie błędu, który był błąd:

var interceptor = ['$q', '$timeout', function ($q, $timeout) {
    function error(rejection) {

            return $q.reject(rejection).finally(function () {
                $timeout(function () {
                    if (rejection.errorHandled === true) {
                        alert('all is under control');
                    } else {
                        alert("Houston we've got problems");
                    }
                }, 0); //zero timeout to execute function after all handlers in chain completed
            });
    }

    return {
        'responseError': error
    };
}];

var exampleOne = $resource('/path').save(objectOne);
exampleOne.$promise.then(function (success) { }, function(error) {
    error.errorHandled = true;
});
0
Yuriy Rozhovetskiy 13 sierpień 2014, 21:12