English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

AngularJSのPromise --- $qサービスの詳細

まずPromiseとは何か、$qとは何かについて説明しましょう。Promiseはアシンクリン処理パターンであり、多くの実装方法があります。有名なKris Kwal's QやJQueryのDeferredなどがあります。

Promiseとは何か

Ajaxについて少しでも知っている人なら、コールバックの苦痛を感じることができます。同期のコードはデバッグしやすいですが、アシンクリンコールバックのコードは開発者が泥沼に陥り、追跡できなくなることがあります:

funA(arg1,arg2,function(){
  funcB(arg1,arg2,function(){
    funcC(arg1,arg2,function(){
       xxxx....
    });
  });  
});

自身のネストが理解しにくいだけでなく、いつコールバックがトリガーされるかもわからないため、これは雪上加霜のようなものです。

しかしPromiseという規格があれば、それは開発者が同期の方法で非同期のコードを書くことができるように助けられます、例えばAngularJSではこのように使用できます:

deferABC.resolve(xxx)
.then(funcSuccess(){},funcError(){},funcNotify(){});

resolve内のオブジェクトが成功すると、funcSuccessがトリガーされ、失敗するとfuncErrorがトリガーされます。これは以下に似ています

deferABC.resolve(function(){
  Success:funcSuccess,
  error:funcError,
  notify:funcNotify
});

もう少し具体的に言えば、Promiseは実行結果が不確定なことを事前に定義したもので、成功した場合にはxxxx;失敗した場合にはxxxxと、事前にいくつかの約束をしたようなものです。

例えば、小白は学校に通っているときにとても怠け者で、いつも同室の人がお弁当を持ってくるように頼んでおり、彼に先に言って、もし菜の花と卵があればその料理を買ってほしい、そうでない場合はトマト炒め卵を買ってほしいと約束していました。買えるかどうかに関わらず、煙草を巻くことを忘れないようにしました。

小白が同室の人がお弁当を持ってくることを頼む
.then(菜の花と卵、トマト炒め卵)
.finally(煙草を巻く)

$qサービス

qサービスはAngularJSで独自に実装されているPromise実装で、Kris Kwal's Qよりも軽量です。
まず$qがよく使われるいくつかのメソッドを紹介します:

defer()はdeferredオブジェクトを作成し、このオブジェクトはresolve、reject、notifyなどの一般的なメソッドを実行できます
all()にPromiseの配列を渡すと、一括で実行し、promiseオブジェクトが返されます
when()に不確定な引数を渡すと、Promise標準に従う場合、promiseオブジェクトが返されます。

Promiseでは、3つの状態を定義しています:待機状態、完了状態、拒否状態。

状態についていくつかの規定があります:

1 状態の変更は逆転できません
2 待機状態は完了状態または拒否状態に変えられます

defer()メソッド

$qでは、resolveメソッドを使用すると完了状態になります;rejectメソッドを使用すると拒否状態になります。

以下は$qの簡単な使用方法を見てみましょう:

<html ng-app="myApp">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script src="http://apps.bdimg.com/libs/angular.js/1.2.16/angular.min.js"></script>
</head>
<body>
  <div ng-controller="myctrl">
    {{test}}
  </div>
  <script type="text/javascript">
     var myAppModule = angular.module("myApp",[]);
     myAppModule.controller("myctrl",["$scope","$q",function($scope, $ q ){
      $scope.test = 1;//これはangularjsが正常に動作しているかのテスト用であり、他の何かの役割はありません。
      var defer1 = $q.defer();
      var promise1 = defer1.promise;
      promise1
      .then(function(value){
        console.log("in promise1 ---- success");
        console.log(value);
      ,function(value){
        console.log("in promise1 ---- error");
        console.log(value);
      ,function(value){
        console.log("in promise1 ---- notify");
        console.log(value);
      });
      .catch(function(e){
        console.log("in promise1 ---- catch");
        console.log(e);
      });
      .finally(function(value){
        console.log('in promise1 ---- finally');
        console.log(value);
      });
      defer1.resolve("hello");
      // defer1.reject("sorry,reject");
     });
  </script>
</body>
</html>

defer()はdeferredオブジェクトを作成するために使われ、defer.promiseはpromiseオブジェクトを返し、thenメソッドを定義するために使われます。thenには成功コールバック、失敗コールバック、状態変更コールバックの3つの引数があります。

resolveに渡された変数や関数の返り値は、最初のthenメソッドの引数として使われます。thenメソッドはpromiseオブジェクトを返すため、以下のように書けることができます。

xxxx
.then(a,b,c)
.then(a,b,c)
.then(a,b,c)
.catch()
.finally()

上記のコードについて続けましょう、then...catch...finallyはJavaのtry...catch...finallyと考えてください。

all()メソッド

このall()メソッドは、複数のpromiseの配列を一つの配列にまとめることができます。すべてのpromiseが成功した後、後続のコールバックが実行されます。コールバックの引数は、各promiseの実行結果です。

大量のメソッドを実行する場合、このメソッドを使用できます。

   var funcA = function(){
        console.log("funcA");
        return "hello,funA";
      }
      var funcB = function(){
        console.log("funcB");
        return "hello,funB";
      }
      $q.all([funcA(),funcB()])
      .then(function(result){
        console.log(result);
      });

実行結果:

funcA
funcB
配列 [ "hello,funA", "hello,funB" ]

when()メソッド

whenメソッドには引数を一つ入れることができます。この引数は値である可能性があり、promise標準に準拠する外部オブジェクトである可能性があります。     

   var funcA = function(){
        console.log("funcA");
        return "hello,funA";
      }
      $q.when(funcA())
      .then(function(result){
        console.log(result);
      });

引数が不定の場合、このメソッドを使用できます。

hello,funA

AngularJSのPromiseについての説明は以上です。 --- $qサービスの詳細な情報を提供し、今後も関連する情報を追加し続けます。皆様のこのサイトへのサポートに感謝します!

声明:この記事の内容はインターネットから取得され、著作権者に帰属します。インターネットユーザーが自発的に貢献し、自己でアップロードしました。このサイトは所有権を持ちません。人工的な編集は行われていません。また、関連する法的責任を負いません。著作権侵害が疑われる内容がある場合は、以下のメールアドレスにご連絡ください:notice#oldtoolbag.com(メールを送信する際、#を@に置き換えてください。報告を行い、関連する証拠を提供してください。一旦確認がついたら、このサイトは侵害される可能性のある内容をすぐに削除します。)

おすすめ