$q

標簽: AngularJS API 中文


-ng模塊下的服務 $q官方文檔

這是一個能幫助你異步地運行函數(shù),并且在他們仍在進程中的時候使用他們的返回值(或者捕捉異常)的服務

$q的靈感源自Kris Kowal的Q,它實現(xiàn)是一個promises/deferred對象。

$q 可以以下面兩種形式來使用 ---
1.類似于Kris Kowal的Q或者jQuery實現(xiàn)的Deferred
2.某種程度上類似于ES6規(guī)范中的promises

$q的構造函數(shù)

$q可以作為一個構造函數(shù),并可以像流式ES6風格的promise一樣使用。它需要一個解析器函數(shù)作為第一個參數(shù)。這與源自ES6 Harmony 的原生Promise的實現(xiàn)方式是十分相似的。詳情見 MDN.
同樣也支持構造風格的編程方式,但是目前還沒有完全支持ES6 Harmony實現(xiàn)的Promise內的所有方法。

可以被這樣使用:

// 此例中,我們假設變量`$ q`和`okToGreet`已經(jīng)存在于當前作用域
// 他們可以通過依賴注入和傳遞參數(shù)來獲取

function asyncGreet(name) { 
  // 執(zhí)行一些異步操作
  // 適當?shù)臅r候解析(resolve)或者阻止(reject) Promise. 

  return $q(function(resolve, reject) { 
    
    setTimeout(function() { 
        
      if (okToGreet(name)) { 
        resolve('Hello, ' + name + '!'); 
      } else { 
        reject('Greeting ' + name + ' is not allowed.');
      } 
            
    }, 1000); 
  });
}

var promise = asyncGreet('Robin Hood');

promise.then(function(greeting) { 

  alert('Success: ' + greeting);
    
}, function(reason) { 

  alert('Failed: ' + reason);
  
});

貼士:進度/通知的回調目前還未在ES6風格里得到支持。

不過,更多的傳統(tǒng)的CommonJS的風格依然可用,并且記錄如下。
The CommonJS Promise 指南 描述 promise 是一個為某個代表著異步操作結果的對象提供互動的接口,而且它的執(zhí)行也并不依賴于某個特定的時間節(jié)點.

從用錯誤處理解決問題的角度來看 deferredpromise 的一些API是異步編程而 trycatchthrow 關鍵字是同步編程.

// 此例中,我們假設變量`$ q`和`okToGreet`已經(jīng)存在于當前作用域
// 他們可以通過依賴注入和傳遞參數(shù)來獲取

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

var promise = asyncGreet('Robin Hood');

promise.then(function(greeting) {

  alert('Success: ' + greeting);
  
}, function(reason) {

  alert('Failed: ' + reason);
  
}, function(update) {

  alert('Got notification: ' + update);
  
});

開始的時候這樣做的好處不是十分明顯的,我們?yōu)槭裁匆黾宇~外的復雜度?看起來十分麻煩。這樣做的好處是源自 promisedeferred API文檔確立的,詳述請看鏈接.
此外,promise API 允許構造是因為使用傳統(tǒng)的回調形式十分困難。更多相關請參考Q 文檔 特別是關于 promise 的串行和并行連接的部分.

Deferred API

一個新的 deferred 實例可以通過調用 $q.defer() 來創(chuàng)建。

這樣暴露出了相關 promise 實例,而且API可以用來廣播成功或失敗的完成,以及任務的狀態(tài)。

方法

  • resolve(value) – 用 value 來解析返回的 promise. 如果 value 是通過 $q.reject 返回的拒絕構造,那么這個 promise 也將被拒絕.
  • reject(reason) – 以 reason 拒絕返回的 promise. 這等同于由 $q.reject 拒絕構造來解析它。
  • notify(value) - 在promise執(zhí)行的狀態(tài)下提供更新. 因此在promise尚未被解析或是拒絕之前會調用很多次.

屬性

  • promise – {Promise} – 與 deferred 相關聯(lián)的 promise 對象.

Promise API

當一個新的 deferred 實例被創(chuàng)建出來,并且可以通過使用 deferred.promise 檢索出來,那么實際上一個新的 promise 實例也被創(chuàng)建出來了.
promise 對象的作用是,允許相關部分獲得當 deferred 任務完成時的結果。

方法

  • then(successCallback, errorCallback, notifyCallback) – 不管promise 已經(jīng)被解析(拒絕)還是將要發(fā)生這些。一但結果為可知的,then都會調用一個成功或者失敗的異步回調函數(shù). 這些回調函數(shù)被調用是只會被傳遞一個單獨的參數(shù): 成功結果或是失敗被拒絕的原因。此外Additionally, the 在 promise 被解析(拒絕)之前,為了提供了一個進度指示 通知回調(notify)可以被調用0到若干次。
    這個方法返回了一個根據(jù)成功 (或失?。?回調函數(shù)返回結果來解析的新的 promise
    (除非返回的結果是一個promise, 而這個promise在這種情況下已經(jīng)由存在于promisepromisevalue 解析)。 依然會通過 notifyCallback 方法的返回值發(fā)布通知。promise 不能由這個 notifyCallback 方法解析或者拒絕。

  • catch(errorCallback) - promise.then(null, errorCallback) 的簡寫

  • finally(callback, notifyCallback) – 雖然允許你觀測一個 promise 的實現(xiàn)(拒絕),但并不會修改最終值。 這對于發(fā)布資源或者為那些需要做處理的被解析(拒絕)的 promise 做一些清理工作十分有用。

鏈接 Promise

由于調用promise下的then方法會返回一個源promise, 這使得創(chuàng)建一條promise鏈變得很容易:

promiseB = promiseA.then(function(result) {
  return result + 1;
});

// 當promiseA被解析之后primiseB會緊接著被解析
// 其值將是promiseA的加1的結果

這有可能會創(chuàng)建一個任意長度的鏈,因為一個promise可以被另一個promise解析(而這個promise將會被近一步的推遲解析),也有可能在這條鏈的任意節(jié)點暫停/推遲解析。這將 實現(xiàn)像$http的相應攔截器那樣強有力的API成為可能.

Kris Kowal's Q 與 $q 之間的區(qū)別

以下是他們之間最主要的區(qū)別:

  • $q 是通過 $rootScope.Scope 集成的,在Angular中作用域模型觀測機制會更快的在你的 model 之間傳播解析或拒絕,這避免不必要的瀏覽器重繪導致的UI閃爍.

  • 盡管 Q$q 有更多的特性,但是這也會帶來增加更多字節(jié)的問題。雖然 $q 是微型的,但是它包含了大多數(shù)異步任務需要的所有重要功能.

測試部分

it('should simulate promise', inject(function($q, $rootScope) {

  var deferred = $q.defer();
  var promise = deferred.promise;
  var resolvedValue;

  promise.then(function(value) { 
    
    resolvedValue = value; 
  });
  
  expect(resolvedValue).toBeUndefined();

  // 模擬解析 promise
  
  deferred.resolve(123);
  
  // 注意! then函數(shù)沒有被同步調用.
  // 這是因為無論 promise 是被同步或是異步調用的,
  // 我們都希望它的 API 總是異步的
  expect(resolvedValue).toBeUndefined();

  // 使用$apply向 then方法傳遞 promise 解析.
  $rootScope.$apply();
  expect(resolvedValue).toEqual(123);
  
}));

依賴

$rootScope


用法

$q(resolver);

參數(shù)

參數(shù) 形式 具體
resolver function(function, function) 函數(shù)是為了響應新創(chuàng)建 promise, 函數(shù)的第一個參數(shù)是用來解析 promise 的函數(shù),函數(shù)的第二個參數(shù)是用來拒絕 promise 的函數(shù).

返回

Promise - 是新創(chuàng)建出的 promise.

方法

1.defer();

  • 創(chuàng)建一個新的 deferred 對象來表示一個將要在未來完成的任務.

返回

Deferred - 是一個 deferred 的新實例.

2.reject(reason);

  • 創(chuàng)建一個由被指定 reason 的拒絕而解析的新的 promise.它的API將被放到 promise 鏈的前面,所以如果你正在處理這個 promise 鏈的最后一個 promise,你并不需要為此感到擔心.

當將 deferreds/promises 和更為熟悉的 try/catch/throw 行為相比較時, 把reject當做Javascript里的 throw 關鍵字. 同樣地如果你“捕獲catchpromise失敗回調返回的error并且你想將此error擲到由當前promise派生出的promise中,你將不得通過借由reject返回的一個拒絕構造來“重拋”這個error.

promiseB = promiseA.then(function(result) {
  // 成功: 執(zhí)行函數(shù)體內部的操作
  //       并用既有或新的結果解析 promiseB
  return result;
  
}, function(reason) {
  // 錯誤: 盡可能處理錯誤,
  //       并用 newPromiseOrValue 解析 promiseB,
  //       否則向promiseB轉發(fā)拒絕
  
  if (canHandle(reason)) {
   // 處理錯誤并恢復
   return newPromiseOrValue;
  
  }
  return $q.reject(reason);
});

參數(shù)

參數(shù) 形式 具體
reason * 常量, 信息, 例外或一個代表拒絕原因的對象.

返回

Promise 返回一個由reason拒絕的 promise.

when(value);
把一個 value 或者一個(第三方)可以使用thenpromise 包裝到一個 $q promise.這樣做的好處是當你再處理一個對象時,你不用再考慮它是不是一個promise,也不必考慮某個外源的 promise 是否是值得信任的.

參數(shù)

參數(shù) 形式 具體
value * value 或一個 promise

返回

Promise - 返回由一個由驗證過的 value 或一個 promise 包裹成的新的 promise.

resolve(value); when的別名,與ES6保持一致.

參數(shù)

參數(shù) 形式 具體
value * value 或一個 promise

返回

Promise 返回由一個由驗證過的 value 或一個 promise 包裹成的新的 promise.

all(promises);

  • 將多個promise合并成一個 promise,它的解析將會在所有輸入的promise解析之后執(zhí)行.

參數(shù)

參數(shù) 形式 具體
promises Array.<Promise> Object.<Promise> 一個數(shù)組或者 promises 的哈希值.

返回

Promise 返回一個單獨的 promise,它將被一組數(shù)組/哈希 value 解析。在這個單獨的 promise 中每一個 value 都會對應到 promise 數(shù)組/哈希的索引中. 如果參數(shù)中的任何一個 promise 被拒絕,這將使由 all 方法返回的 promise 被同樣的理由(上面的拒絕)拒絕掉.

本文由作者原創(chuàng),翻譯內容仍有欠佳之處,請大家多多指正。via 村里有個村長 / @西瓜橘子葡萄冰

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容