2013-04-08 11 views
24

Mam ten prosty kod:

$http.get("/api/test") 
    .success(function (data, status, headers, config) { 
     console.log(data); 
     return data; 
    }).error(function (data, status, headers, config) { 
     alert("error"); 
     return status; 
}); 

To działa dobrze, ale funkcja błędu nigdy nie jest wywoływana, nawet gdy wrócę 404 (nie znaleziono) z serwerem .. W takim przypadku wywołuje funkcję "powodzenie" o statusie = 404 ...

Czy to prawda?

Dzięki

Skrzypek:

Request 

GET http://localhost:41234/api/test HTTP/1.1 
Host: localhost:41234 
Connection: keep-alive 
Accept: application/json, text/plain, */* 
X-Requested-With: XMLHttpRequest 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22 
Referer: http://localhost:41234/ 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 
Cookie: ASP.NET_SessionId=bd1b3rib5j4beub0xbuhb1hm; FormsAuthentication=xxxxx 

Response 

HTTP/1.1 404 Not Found 
Cache-Control: no-cache 
Pragma: no-cache 
Expires: -1 
Server: Microsoft-IIS/8.0 
X-AspNet-Version: 4.0.30319 
X-SourceFiles: =?UTF-8?B?RDpcUGVzc29hxvY2FyLkFwaVxhcGcg==?= 
X-Powered-By: ASP.NET 
Content-Length: 0 

Odpowiedz

5

Problemem jest serwer, to jest ustawienie Content-Length na 0 to oznacza, że ​​jest to ważna wartość, jak widać na HTTP/1.1 specification.

Zrobiłem również przykład na JSFiddle pokazujący przykłady błędów i sukcesów. Zobacz here.

Nagłówki z przykładu błędu:

Zapytanie:

GET /error/ HTTP/1.1 
Host: fiddle.jshell.net 
Connection: keep-alive 
Accept: application/json, text/plain, */* 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31 
DNT: 1 
Referer: http://fiddle.jshell.net/danielcsgomes/cAMc6/1/show/ 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 
Accept-Charset: UTF-8,*;q=0.5 
Cookie: csrftoken=4tNVNxC5v6BSq9yJCKkHlGFJBz3cClqd` 

Response:

HTTP/1.1 404 NOT FOUND 
Server: nginx/0.8.54 
Date: Fri, 12 Apr 2013 00:38:07 GMT 
Content-Type: text/html; charset=utf-8 
Transfer-Encoding: chunked 
Connection: keep-alive 
Vary: Cookie 
Content-Encoding: gzip 
+3

To jest nieprawidłowe. Angularjs nie dba o długość treści. – AgDude

+4

Ta odpowiedź nie powinna być oznaczona jako prawidłowa, w rzeczywistości jest niepoprawna, jak wspomniał AgDude. Dla mnie właściwą odpowiedzią była ta z @wilver (patrz poniżej)! – Nabi

3

Jeśli używasz angularjs wersji 1.1.1 lub większe ...

Czy dodanie pracy '.json' ?:

$http.get("/api/test.json") 
    .success(function (data, status, headers, config) { 
     console.log(data); 
     return data; 
    }).error(function (data, status, headers, config) { 
     alert("error"); 
     return status; 
}); 

Jeśli tak, można go również naprawić za pomocą:

myModule.config(['$httpProvider', function ($httpProvider) { 
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 
}]); 

Zobacz ten =>Angular JS Fails After Upgrade from 1.1.0 to 1.1.1

+0

Witam, dołączając .json generuje ten błąd: { "message": "Nie znaleziono zasobu HTTP pasującego do identyfikatora URI żądania" http: // localhost: 4021/api/test.json '. "," messageDetail ":" Nie znaleziono typu odpowiadającego kontrolerowi o nazwie "user". json '. "} ... Używam .NET Web API na serwerze ... – Paul

+0

Dodałem zapytanie/odpowiedź fiddlera do pytania – Paul

+0

dlaczego zmiana pomocy rozszerzenia w tej konkretnej sytuacji ... Nie widzę it –

24

miałem ten sam problem i szczerze, przestrzegać wskazówek o tym poście umieścić mnie w niewłaściwym kierunku ... , więc podzielę się moją sprawą/rozwiązaniem, aby inni w tej samej sytuacji mogli zaoszczędzić czas.

Używam angularjs 1.2.14 + WebAPI 2. to moja odpowiedź na status NOTFOUND:

Cache-Control:no-cache 
Content-Length:0 
Date:Sat, 15 Mar 2014 14:28:35 GMT 
Expires:-1 
Pragma:no-cache 
Server:Microsoft-IIS/8.0 
X-AspNet-Version:4.0.30319 
X-Powered-By:ASP.NET 
X-SourceFiles:=?UTF-8?B?QzpcU3ZpbHVwcG9EaXNjaXR1clxhcGlcTWFnMTRcYXBpXGxlc3Nvblw4NA==?= 

Jak widać, Content-wyciągów: 0, ale to jest ok.

Mój problem był Niepoprawny wykorzystanie angularjs kolektora, w szczególności mniej więcej tak:

responseError: function (result) { 
       // check something 
       return result; 
      } 

powrocie wynik bez wyjątek lub odrzucanie obietnice (as written in docs) sprawia kątowa uwierzyć, że chcesz przekonwertować odrzucenie w prawidłowej rozdzielczości, a następnie wywołanie zwrotne sukcesu.

poprawiam mój kod następująco:

responseError: function (result) {      
       // check something 
       return $q.reject(result); 
      } 
0

Przenieśliśmy stanowisko do fabryki, nie dbam tu o testowaniu $ http rzeczy, po prostu to, co robi w przypadku powodzenia lub błędu:

factoryModule.factory('GiftFactory', function ($http, Settings) { 
    var saveUrl = Settings.endpoints.saveUrl; 

    return { 
     createGift: function (data) { 
      var gift = { gift: JSON.stringify(angular.toJson(data.gift)) }; 
      return $http.post(saveUrl, gift); 
     } 
    }; 
}); 

nazywamy go tak:

$scope.submit = function() { 
     $scope.submitting = true; 
     GiftFactory.createGift($scope) 
      .success(function() { 
       $window.location = Giving.endpoints.indexUrl; 
      }).error(function() { 
       $scope.submitting = false; 
       alert('an error occurred'); 
     }); 
    }; 

Testujemy to tak:

describe('donation controller', function() { 
var $scope, q, window, controller; 

beforeEach(module('giving.donation')); 
beforeEach(inject(function ($controller, $rootScope, $q) { 
    $scope = $rootScope.$new(); 
    window = {}; 
    q = $q; 
    giftFactory = {}; 
    controller = $controller('DonationController', { $scope: $scope, $window: window, GiftFactory: giftFactory }); 
})); 

describe('submit', function() { 
    var deferred; 
    beforeEach(function() { 
     deferred = q.defer(); 

     deferred.promise.success = function (fn) { 
      deferred.promise.then(
       function (response) { 
        fn(response.data, response.status, response.headers); 
       }); 
      return deferred.promise; 
     }; 
     deferred.promise.error = function (fn) { 
      deferred.promise.then(null, 
       function (response) { 
        fn(response.data, response.status, response.headers); 
       }); 
      return deferred.promise; 
     }; 
    }); 

    it('should redirect on success', function() { 
     //Arrange 
     Giving = { endpoints: { indexUrl: "/testurl" } }; 

     giftFactory.createGift = function() { 
      return deferred.promise; 
     }; 

     //Act 
     $scope.submit(); 

     deferred.resolve({}); 
     $scope.$apply(); 

     //Assert 
     expect($scope.submitting).toBeTruthy(); 
     expect(window.location).toBe('/testurl'); 
    }); 

    it('should set submitting back to false on error', function() { 
     //Arrange 
     Giving = { endpoints: { indexUrl: "/testurl" } }; 

     giftFactory.createGift = function() { 
      return deferred.promise; 
     }; 

     //Act 
     $scope.submit(); 

     deferred.reject({}); 
     $scope.$apply(); 

     //Assert 
     expect($scope.submitting).toBeFalsy(); 
     expect(window.location).toBeUndefined(); 
    }); 
}); 

}); 
2

Może trochę późno, ale ... Na życzenie $ http chwili kątowa daje przesłankę, dzięki czemu można go zmienić na:

$http({ 
    method: "yourMethod", 
    url: "yourUrl", 
    data: {yourDataObj} 
}).then(function (res) {  //first function "success" 
    console.log(res.data); 
}, function (err) {   //second function "error" 
    console.log(err); 
}); 
Powiązane problemy