118

私は$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
    });

これは良い方法ですか、それとももっと簡単な方法はありますか?

4

6 に答える 6

106

Promise はステートメントを抽象化したものであり、非同期コードと同期して自分自身を表現できるようにします。これらは、1 回限りのタスクの実行を表します。

また、通常のコードと同様に例外処理も提供します。Promise から戻るか、スローすることができます。

同期コードで必要なのは次のとおりです。

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.
});
于 2014-05-09T08:32:12.580 に答える
44

successanderrorメソッドの使用を忘れてください。

どちらの方法も angular 1.4 で廃止されました。基本的に、非推奨の背後にある理由は、いわばチェーン可能ではないということです

次の例で、チェーン可能ではないということについてsuccess、私が何を意味するかを実証しようとします。アドレスを持つユーザー オブジェクトを返す API を呼び出すとします。error

ユーザー オブジェクト:

{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元の promise、つまり によって返されたものを返すため$http.get、 のコールバックに渡されるオブジェクトはユーザーthenオブジェクト全体、つまり前のコールバックへの同じ入力です。success

two を連鎖させていればthen、これはそれほど混乱しませんでした:

$http.get('/user')
    .then(function (user) {
        return user.address;  
    })
    .then(function (obj) {  
        console.log(obj); // -> 'San Francisco'
    });
};
于 2015-10-22T17:30:39.597 に答える
-3

Bradley Braithwaite が彼のブログで提案しているように、私はそれを行います。

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;
            });
    }])

キーポイント:

  • 解決関数は、コントローラーの .then 関数にリンクします。つまり、すべてが順調であるため、約束を守り、解決することができます。

  • reject 関数は、コントローラーの .catch 関数にリンクしています。つまり、何か問題が発生したため、約束を守ることができず、拒否する必要があります。

それは非常に安定しており、安全であり、約束を拒否する他の条件がある場合は、いつでも成功関数でデータをフィルタリングしdeferred.reject(anotherReason)、拒否の理由で呼び出すことができます.

コメントで Ryan Vice が示唆したように、いわば応答を少しいじらない限り、これは有用とは見なされない可能性があります。

successとは 1.4 以降非推奨であるためerror、通常の promise メソッドを使用し、それらのメソッド内で応答を変換して、その変換された応答の promise を返す方がよいでしょthencatch

両方のアプローチと 3 番目の中間アプローチで同じ例を示しています。

successそしてerrorアプローチします(successそしてerrorHTTP応答のpromiseを返すので$q、データのpromiseを返すにはの助けが必要です):

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;
};

thencatchアプローチします(スローのため、これはテストが少し難しくなります):

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;
}

ただし、中途半端な解決策があります (この方法で回避でき、とにかく、テストで約束の動作をモックするthrowために使用する必要があるでしょう):$q

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;
}

どんな種類のコメントや修正も大歓迎です。

于 2016-06-13T09:33:43.430 に答える