Angularjs中的promise

promise 是一種用異步方式處理值的方法,promise是對象,表明了一個函數最終可能的返回值或拋出的異常。在與遠程對象打交道很是有用,能夠把它們當作一個遠程對象的代理。html

要在Angular中建立promise須要使用內置的$q服務。先用factory定義一個服務,注入$q服務。jquery

angular.module('readApp').factory('asyncService', [
    "$q", function ($q) {
         var myAsync=function(flag) {
            var deferred = $q.defer();
            if (flag) {
                deferred.resolve("well done!");
            } else {
                deferred.reject("lost!");
            }
             return deferred.promise;
         }
        return {
            myAsync: myAsync
        };
    }
]);

 得到deferred的方法和jquery不一樣,但resolve和reject是同樣的,最後返回的是promise屬性,而不是promise方法。再看如何調用:git

angular.module('readApp').controller('testCtrl', ["$scope", "asyncService", function ($scope, asyncService) {
        $scope.flag = true;
        $scope.handle = function () {
            asyncService.myAsync($scope.flag).then(function (result) {
                $scope.status = result;
                return result;
            }, function (error) {
                $scope.status = error;
                return error;
            });
        }
    }])

獲取到服務後,調用then方法。then有三個參數,分別對應成功回調、失敗回調和通知回調。這個和jquery是一致的github

<div  class="container">
    <label for="flag">成功
        <input type="checkbox" id="flag" ng-model="flag" name="name" /> <br />
        <div>{{status}}</div>
        <button ng-click="handle()">點擊</button>
    </label>
</div>
<footer-n

結果:  數組

不一樣的是,Angular的promise沒有公佈jquery那麼多方法,咱們能夠看一下deferred.promise這個屬性,它是一個$$state對象。根據Promise/A規範,一個Promise只要具有一個then方法便可。promise

注意到,Angular中的deferred有notify、reject、resolve三個主要方法和一個promise屬性,而這個promise的原型連中包含了咱們調用的then方法,then方法在執行完以後會派生一個新的promise,所以能夠鏈式調用。沒有done和fail,可是還提供了catch和finally方法。catch就至關因而error方法了。而finally方法就像強類型語言中的場景同樣,當咱們須要釋放一個資源,或者是運行一些清理工做,無論promise是成功仍是失敗時,這個方法會頗有用。要注意的是finally是ie中的一個保留字,須要下面這樣調用:異步

promise['finally'](function() {});

  

除了defer()方法,$q還有all和when方法,all(promises)能夠將多個promise合併成一個,但若是任意一個promise拒絕了,那麼結果的promise也會拒絕。而when(value)方法把一個多是值或者promise包裝成一個$q promise。有了jQuery中的when,這兩個方法不難理解。關於這三個方法的示例能夠參考這篇博客:AngularJS 中的Promise --- $q服務詳解async

Angular的$q的靈感是來自[Kris Kowal's Q],從官方的註釋中能夠看到函數

 * This is an implementation of promises/deferred objects inspired by
 * [Kris Kowal's Q](https://github.com/kriskowal/q).
  * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
  * implementations, and the other which resembles ES6 promises to some degree.

  支持兩種風格,能夠像Q庫或者jQuery的deferred同樣,也能夠用ES6語法,文檔給出了示例,也是就構造函數法來定義:post

var asyncGreet = function (name) {
            return $q(function (resolve, reject) {
                console.log(resolve, reject);
                setTimeout(function () {
                    if (name=="stone") {
                        resolve('Hello, ' + name + '!');
                    } else {
                        reject('Greeting ' + name + ' is not allowed.');
                    }
                }, 1000);
            });
        };

  通知(notify/progress)回調還不支持這種寫法。對比看,沒太大差異。

  

function asyncGreet(name) {
    var deferred = $q.defer();
    setTimeout(function() {
     deferred.notify('About to greet ' + name + '.');
     if (okToGreet(name)) {
        deferred.resolve('Hello, ' + name + '!');
      } else {
        deferred.reject('Greeting ' + name + ' is not allowed.');
      }
     }, 1000);
   return deferred.promise;
  }

 大體看下源碼如何實現:

 Promise:

 

 

function Promise() {
    this.$$state = { status: 0 };
  }

  extend(Promise.prototype, {
    then: function(onFulfilled, onRejected, progressBack) {
      if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) {
        return this;
      }
      var result = new Deferred();

      this.$$state.pending = this.$$state.pending || [];
      this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
      if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);

      return result.promise;
    },

    "catch": function(callback) {
      return this.then(null, callback);
    },

    "finally": function(callback, progressBack) {
      return this.then(function(value) {
        return handleCallback(value, true, callback);
      }, function(error) {
        return handleCallback(error, false, callback);
      }, progressBack);
    }
  });

建立了一個Promise對象包含一個$$state屬性,而後擴展了then,catch,finally方法(注意後兩個帶了引號)。then的三個參數都是回調函數,對應成功、失敗、通知回調,並在then方法中建立了一個deferred做爲結果,將回調函數和建立的deferred都存入了數組,主意到這是一個二維數組,每一個then對應的promise和回調函數都在這個數組裏面。最後返回promise。而catch和finally內部也是調用的then。只要狀態大於0也就promise得到告終果就用scheduleProcessQueue處理回調。 Deferred 內部包含了一個promise以及resolve、reject和notify三個方法。jQuery.deferred 中處理的是三個回調隊列,Angular中處理的一個是二維數組。 

$http的是一個promise對象:

var promise = $q.when(config);
       //some code
       
        promise = promise.then(thenFn, rejectFn);
      }
      if (useLegacyPromise) {
        promise.success = function(fn) {
          assertArgFn(fn, 'fn');
          promise.then(function(response) {
            fn(response.data, response.status, response.headers, config);
          });
          return promise;
        };
        promise.error = function(fn) {
          assertArgFn(fn, 'fn');

          promise.then(null, function(response) {
            fn(response.data, response.status, response.headers, config);
          });
          return promise;
        };
      } else {
        promise.success = $httpMinErrLegacyFn('success');
        promise.error = $httpMinErrLegacyFn('error');
      }

      return promise;

用then擴展了error和succes方法,所以咱們能夠這樣使用:

booksData.getbookById(bookid).success(function(data) {
            vm.book = data;
        }).error(function (e) {
            console.log(e);
            vm.message = "Sorry, something's gone wrong ";
        });

$Interval也是一個promise對象。  

AngularJS 中的Promise --- $q服務詳解

http://www.cnblogs.com/xing901022/p/4928147.html  

相關文章
相關標籤/搜索