web-dev-qa-db-ja.com

AngularJSの約束で成功/エラー/ついに/ catchを使用する

私はAngularJで$httpを使っていますが、返されたpromiseの使い方やエラー処理の仕方についてはよくわかりません。

私はこのコードを持っています:

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

これはそれを行うための良い方法ですか、それとももっと簡単な方法がありますか?

108
Joel

約束は、非同期コードと同期して自分自身を表現できるようにするステートメントを抽象化したものです。それらはワンタイムタスクの実行を表します。

それらはまた、通常のコードと同じように、例外処理を提供します。約束から戻ることも、スローすることもできます。

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

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.
});
96

successおよびerrorメソッドの使用を忘れます。

どちらの方法も角度1.4では推奨されていません。基本的に、非推奨の背景にある理由は、それらがchainable-friendlyではないということです。

次の例では、successerrorchainable-friendlyではないことの意味を説明します。アドレスを持つユーザーオブジェクトを返す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'}
    });
};

何があったの?

successerrororiginal promise、つまり$http.getによって返されるものを返すので、thenのコールバックに渡されるオブジェクトは全体ですserつまり、前のsuccessコールバックへの同じ入力です。

2つのthenをチェーニングしたなら、これはそれほど混乱しないでしょう:

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

私は前の答えは正しいと思います、しかしここにもう一つの例があります(ちょうどf.y.i、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');
    });
35
grepit

どのような粒度を探していますか?通常は次のようにして取得できます。

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

複数の約束を結びつけるときは、 "finally"と "catch"の方が良いことがわかりました。

11
justin

Angular $ httpの場合、success()関数とerror()関数は応答オブジェクトのラップを解除するので、コールバックシグネチャは$ http(...)のようになります。 、ヘッダー、設定)

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(...)は、前のプロミスチェーンで新しいエラーが発生しない限り必要ありません。

5
zd333