Programming

AngularJS에서 약속과 함께 성공 / 오류 / 최종 / 캐치를 사용

procodes 2020. 8. 3. 21:51
반응형

AngularJS에서 약속과 함께 성공 / 오류 / 최종 / 캐치를 사용


내가 사용하고 $httpAngularJS와에, 나는 반환 약속을 사용하는 방법과 핸들 오류를 모르겠어요.

이 코드가 있습니다 :

$http
    .get(url)
    .success(function(data) {
        // Handle data
    })
    .error(function(data, status) {
        // Handle HTTP error
    })
    .finally(function() {
        // Execute logic independent of success/error
    })
    .catch(function(error) {
        // Catch and handle exceptions from success/error/finally functions
    });

이것이 좋은 방법입니까, 아니면 쉬운 방법입니까?


약속은 우리가 비동기 코드로 동기식으로 표현할 수 있도록하는 명령문에 대한 추상화입니다. 일회성 작업의 실행을 나타냅니다.

또한 일반 코드와 마찬가지로 예외 처리 기능을 제공하므로 약속에서 돌아 오거나 던질 수 있습니다.

동기 코드에서 원하는 것은 다음과 같습니다.

try{
  try{
      var res = $http.getSync("url");
      res = someProcessingOf(res);
  } catch (e) {
      console.log("Got an error!",e);
      throw e; // rethrow to not marked as handled
  }
  // do more stuff with res
} catch (e){
     // handle errors in processing or in error.
}

약속 된 버전은 매우 비슷합니다.

$http.get("url").
then(someProcessingOf).
catch(function(e){
   console.log("got an error in initial processing",e);
   throw e; // rethrow to not marked as handled, 
            // in $q it's better to `return $q.reject(e)` here
}).then(function(res){
    // do more stuff
}).catch(function(e){
    // handle errors in processing or in error.
});

사용 잊어 successerror방법에 관한 것이다.

두 방법 모두 각도 1.4에서 더 이상 사용되지 않습니다. 기본적으로 더 이상 사용되지 않는 이유는 체인 친화적 이지 않기 때문 입니다.

다음의 예를 통해, 나는에 대해 무엇을 의미하는지 설명하려고합니다 successerror되지 인 체인 방식 친화적 인 . 주소가있는 사용자 객체를 반환하는 API를 호출한다고 가정 해 보겠습니다.

사용자 객체 :

{name: 'Igor', address: 'San Francisco'}

API를 호출하십시오.

$http.get('/user')
    .success(function (user) {
        return user.address;   <---  
    })                            |  // you might expect that 'obj' is equal to the
    .then(function (obj) {   ------  // address of the user, but it is NOT

        console.log(obj); // -> {name: 'Igor', address: 'San Francisco'}
    });
};

어떻게 된 거예요?

때문에 successerror반환 원래의 약속 , 즉에 의해 반환되는 한 $http.get,의 콜백에 전달 된 개체가 then전체 인 사용자 이전에 동일한 입력 말을하는 것입니다 객체, success콜백.

우리가 2를 연결했다면 then, 혼란이 덜했을 것입니다.

$http.get('/user')
    .then(function (user) {
        return user.address;  
    })
    .then(function (obj) {  
        console.log(obj); // -> 'San Francisco'
    });
};

이전 답변이 맞다고 생각하지만 여기에 또 다른 예가 있습니다 (Fayi, success () 및 error ()는 AngularJS 메인 페이지 에 따라 더 이상 사용되지 않습니다 :

$http
    .get('http://someendpoint/maybe/returns/JSON')
    .then(function(response) {
        return response.data;
    }).catch(function(e) {
        console.log('Error: ', e);
        throw e;
    }).finally(function() {
        console.log('This finally block');
    });

어떤 유형의 세분성을 찾고 있습니까? 일반적으로 다음을 수행 할 수 있습니다.

$http.get(url).then(
  //success function
  function(results) {
    //do something w/results.data
  },
  //error function
  function(err) {
    //handle error
  }
);

여러 약속을 연결할 때 "최종"과 "캐치"가 더 나은 것으로 나타났습니다.


Angular $ http의 경우 success () 및 error () 함수는 응답 객체가 래핑되지 않으므로 콜백 서명은 $ http (...)와 같습니다 .success (function (data, status, headers, config))

then ()의 경우 아마도 원시 응답 객체를 처리 할 것입니다. AngularJS $ http API 문서에 게시 된 것과 같은

$http({
        url: $scope.url,
        method: $scope.method,
        cache: $templateCache
    })
    .success(function(data, status) {
        $scope.status = status;
        $scope.data = data;
    })
    .error(function(data, status) {
        $scope.data = data || 'Request failed';
        $scope.status = status;
    });

이전 약속 체인에서 새로운 오류가 발생하지 않으면 마지막 .catch (...)가 필요하지 않습니다.


I do it like Bradley Braithwaite suggests in his blog:

app
    .factory('searchService', ['$q', '$http', function($q, $http) {
        var service = {};

        service.search = function search(query) {
            // We make use of Angular's $q library to create the deferred instance
            var deferred = $q.defer();

            $http
                .get('http://localhost/v1?=q' + query)
                .success(function(data) {
                    // The promise is resolved once the HTTP call is successful.
                    deferred.resolve(data);
                })
                .error(function(reason) {
                    // The promise is rejected if there is an error with the HTTP call.
                    deferred.reject(reason);
                });

            // The promise is returned to the caller
            return deferred.promise;
        };

        return service;
    }])
    .controller('SearchController', ['$scope', 'searchService', function($scope, searchService) {
        // The search service returns a promise API
        searchService
            .search($scope.query)
            .then(function(data) {
                // This is set when the promise is resolved.
                $scope.results = data;
            })
            .catch(function(reason) {
                // This is set in the event of an error.
                $scope.error = 'There has been an error: ' + reason;
            });
    }])

Key Points:

  • The resolve function links to the .then function in our controller i.e. all is well, so we can keep our promise and resolve it.

  • The reject function links to the .catch function in our controller i.e. something went wrong, so we can’t keep our promise and need to reject it.

It is quite stable and safe and if you have other conditions to reject the promise you can always filter your data in the success function and call deferred.reject(anotherReason) with the reason of the rejection.

As Ryan Vice suggested in the comments, this may not be seen as useful unless you fiddle a bit with the response, so to speak.

Because success and error are deprecated since 1.4 maybe it is better to use the regular promise methods then and catch and transform the response within those methods and return the promise of that transformed response.

I am showing the same example with both approaches and a third in-between approach:

success and error approach (success and error return a promise of an HTTP response, so we need the help of $q to return a promise of data):

function search(query) {
  // We make use of Angular's $q library to create the deferred instance
  var deferred = $q.defer();

  $http.get('http://localhost/v1?=q' + query)
  .success(function(data,status) {
    // The promise is resolved once the HTTP call is successful.
    deferred.resolve(data);              
  })

  .error(function(reason,status) {
    // The promise is rejected if there is an error with the HTTP call.
    if(reason.error){
      deferred.reject({text:reason.error, status:status});
    }else{
      //if we don't get any answers the proxy/api will probably be down
      deferred.reject({text:'whatever', status:500});
    }
  });

  // The promise is returned to the caller
  return deferred.promise;
};

then and catch approach (this is a bit more difficult to test, because of the throw):

function search(query) {

  var promise=$http.get('http://localhost/v1?=q' + query)

  .then(function (response) {
    // The promise is resolved once the HTTP call is successful.
    return response.data;
  },function(reason) {
    // The promise is rejected if there is an error with the HTTP call.
    if(reason.statusText){
      throw reason;
    }else{
      //if we don't get any answers the proxy/api will probably be down
      throw {statusText:'Call error', status:500};
    }

  });

  return promise;
}

There is a halfway solution though (this way you can avoid the throw and anyway you'll probably need to use $q to mock the promise behavior in your tests):

function search(query) {
  // We make use of Angular's $q library to create the deferred instance
  var deferred = $q.defer();

  $http.get('http://localhost/v1?=q' + query)

  .then(function (response) {
    // The promise is resolved once the HTTP call is successful.
    deferred.resolve(response.data);
  },function(reason) {
    // The promise is rejected if there is an error with the HTTP call.
    if(reason.statusText){
      deferred.reject(reason);
    }else{
      //if we don't get any answers the proxy/api will probably be down
      deferred.reject({statusText:'Call error', status:500});
    }

  });

  // The promise is returned to the caller
  return deferred.promise;
}

Any kind of comments or corrections are welcome.

참고URL : https://stackoverflow.com/questions/23559341/using-success-error-finally-catch-with-promises-in-angularjs

반응형