angularjs 異步回調管理的機制


和其它框架一樣, ng 提供了廣義的異步回調管理的機制。 $http 服務是在其之上封裝出來的。這個機制就是 ng 的 $q 服務。

不過 ng 的這套機制總的來說實現得比較簡單,按官方的說法,夠用了。

使用的方法,基本上是:

  • 通過 $q 服務得到一個 deferred 實例
  • 通過 deferred 實例的 promise 屬性得到一個 promise 對象
  • promise 對象負責定義回調函數
  • deferred 實例負責觸發回調
  var TestCtrl = function($q){
    var defer = $q.defer();
    var promise = defer.promise;
    promise.then(function(data){console.log('ok, ' + data)},
                 function(data){console.log('error, ' + data)});
    //defer.reject('xx');
    defer.resolve('xx');
  }

了解了上面的東西,再分別看 $q , deferred , promise 這三個東西。

11.2.1. $q

$q 有四個方法:

  • $q.all() 合並多個 promise ,得到一個新的 promise
  • $q.defer() 返回一個 deferred 對象
  • $q.reject() 包裝一個錯誤,以使回調鏈能正確處理下去
  • $q.when() 返回一個 promise 對象

$q.all() 方法適用於並發場景很合適:

var TestCtrl = function($q, $http){
    var p = $http.get('/json', {params: {a: 1}});
    var p2 = $http.get('/json', {params: {a: 2}});
    var all = $q.all([p, p2]);
    p.success(function(res){console.log('here')});
    all.then(function(res){console.log(res[0])});
  }

$q.reject() 方法是在你捕捉異常之后,又要把這個異常在回調鏈中傳下去時使用:

要理解這東西,先看看 promise 的鏈式回調是如何運作的,看下面兩段代碼的區別:

  var defer = $q.defer();
  var p = defer.promise;
  p.then(
    function(data){return 'xxx'}
  );
  p.then(
    function(data){console.log(data)}
  );
  defer.resolve('123');
  var defer = $q.defer();
  var p = defer.promise;
  var p2 = p.then(
    function(data){return 'xxx'}
  );
  p2.then(
    function(data){console.log(data)}
  );
  defer.resolve('123');

從模型上看,前者是“並發”,后者才是“鏈式”。

而 $q.reject() 的作用就是觸發后鏈的 error 回調:

  var defer = $q.defer();
  var p = defer.promise;
  p.then(
    function(data){return data},
    function(data){return $q.reject(data)}
  ).
  then(
    function(data){console.log('ok, ' + data)},
    function(data){console.log('error, ' + data)}
  )
  defer.reject('123');

 

最后的 $q.when() 是把數據封裝成 promise 對象:

  var p = $q.when(0, function(data){return data},
                     function(data){return data});
  p.then(
    function(data){console.log('ok, ' + data)},
    function(data){console.log('error, ' + data)}
  );

 

11.2.2. deferred

deferred 對象有兩個方法一個屬性。

  • promise 屬性就是返回一個 promise 對象的。
  • resolve() 成功回調
  • reject() 失敗回調
  var defer = $q.defer();
  var promise = defer.promise;
  promise.then(function(data){console.log('ok, ' + data)},
               function(data){console.log('error, ' + data)});
  //defer.reject('xx');
  defer.resolve('xx');

 

11.2.3. promise

promise 對象只有 then() 一個方法,注冊成功回調函數和失敗回調函數,再返回一個 promise 對象,以用於鏈式調用。

promise是頭等對象,自帶了一些約定。
 只有一個resolve或者reject會被調用到:
 resolve被調用時,帶有一個履行值;
 reject被調用時要帶一個拒絕原因。
 如果promise被執行或者拒絕了,依賴於它們的處理程序仍然會被調用;
 處理程序總是會被異步調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM