$q -- AngularJS中的服務(理解)

來源:互聯網
上載者:User

標籤:參考   建議   .com   改變   .net   alt   恢複   eth   data-   

 描述

譯者注: 看到了一篇非常好的文章,如果你有興趣,可以查看: Promises與Javascript非同步編程 , 裡面對Promises規範和使用情景,好處講的非常好透徹,個人覺得簡單易懂。

既然是用來處理非同步編程的,那麼在瀏覽器端的JS裡,主要是2種: setTimeout 和 Ajax 請求.  promise 的使用就很像Ajax請求的成功和失敗回調。

 

此承諾/延遲(promise/deferred)實現的靈感來自於  Kris Kowal‘s Q CommonJS Promise建議文檔 將承諾(promise) 作為和 非同步執行操作(action)結果對象進行互動的介面,在指定的時間內可能完成也可能不能夠完成(如逾時,錯誤,攔截等等)。

從錯誤處理的角度看,延遲( deferred )和承諾( promise ) API 對於非同步編程來說, 和同步編程的 try,catch, 以及throw作用差不多.
[javascript] view plain copy  
  1. // 為了示範的目的,此處我們假設 `$q`, `scope` 以及 `okToGreet` 引用 在當前執行環境中可用  
  2. // (比如他們已經被注入,或者被當做參數傳進來了).  
  3.    
  4. function asyncGreet(name) {  
  5.   var deferred = $q.defer();  
  6.    
  7.   setTimeout(function() {  
  8.     // 因為此function 在未來的事件迴圈中非同步執行,  
  9.     // 我們需要把程式碼封裝裝到到一個 $apply 調用中,以便正確的觀察到 model 的改變  
  10.     scope.$apply(function() {  
  11.       deferred.notify(‘即將問候 ‘ + name + ‘.‘);  
  12.    
  13.       if (okToGreet(name)) {  
  14.         deferred.resolve(‘你好, ‘ + name + ‘!‘);  
  15.       } else {  
  16.         deferred.reject(‘拒絕問候 ‘ + name + ‘ .‘);  
  17.       }  
  18.     });  
  19.   }, 1000);  
  20.    
  21.   return deferred.promise;  
  22. }  
  23.    
  24. var promise = asyncGreet(‘小漠漠‘);  
  25. promise.then(function(greeting) {  
  26.   alert(‘成功: ‘ + greeting);  
  27. }, function(reason) {  
  28.   alert(‘失敗鳥: ‘ + reason);  
  29. }, function(update) {  
  30.   alert(‘收到通知: ‘ + update);  
  31. });  

引人這種額外的複雜性的效果 在起初可能不明顯。 在 promise 和 deferred APIs 進行承諾時好處就看出來了,請參考:  https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md
另外 promise api允許那些在傳統的回調( CPS )方法中很難的實現的組合。 更多資訊請查閱  Q文檔 ,特別是 串列與並行的合并一節。
延遲介面 | Deferred API通過調用  $q.defer() 可以構建一個新的 deffered 執行個體。
deffered 對象用來將 Promise 執行個體與 標記任務狀態(執行成功還是不成功)的 API 相關聯。
deffered 對象的方法
  • resolve(value) ——傳入 value 解決派生的 promise。 如果 value 是一個通過 $q.reject 構造的拒絕對象(rejection) , 該promise 將被拒絕。
  • reject(reason) ——拒絕派生的promise,並提供原因 。 這相當於通過 $q.reject構造的拒絕對象(rejection)作為參數傳遞給 resolve。
  • notify(value)  ——在 promise 執行的過程中提供狀態更新。 這在 promise 被解決或拒絕之前可能會被多次調用。
deffered 對象的屬性promise – {Promise} —— 與延遲(deferred)相關聯的 promise 對象。
承諾 介面 | Promise API當建立 deferred 執行個體時會建立一個新的 promise 對象,並可以通過  deferred.promise 得到該引用。
promise 對象的目的是在 deferred 任務完成時,允許感興趣的部分取得其執行結果。
promise 對象的方法
  • then(successCallback, errorCallback, notifyCallback) ——不管 promise 是被處理還是被拒絕, 一旦結果可用,then 就會儘快地非同步呼叫 成功/錯誤 回呼函數 只要結果是可用的。 調用回呼函數時傳遞單個參數: 結果 或拒絕的理由。 此外,notify 回調可能被調用 0到多次,以提供 提供一個進度指示,之前承諾解決或拒絕。
           這個方法 返回一個新的promise 對象, 根據 successCallback , errorCallback的傳回值進行解決或拒絕 。 它還通過 notifyCallback 方法的傳回值進行通知。 promise 不能從notifyCallback方法得到解決或拒絕 。
  • catch(errorCallback) —— promise.then(null, errorCallback) 的捷徑
  • finally(callback) ——讓你可以觀察到一個 promise 是被執行還是被拒絕, 但這樣做不用修改最後的 value值。 這可以用來做一些釋放資源或者清理無用對象的工作,不管promise 被拒絕還是解決。 更多的資訊請參閱完整文檔規範.
            因為在 ES3版本的JavaScript中 finally 是一個保留字關鍵字,不能作為屬性名稱,為了適配 IE8,您需要使用  promise[‘finally‘](callback) 這種形式來調用該方法。
promise 鏈 | Chaining promises因為調用一個 promise 的 then 方法返回一個新的派生 promise執行個體,所以構建promises鏈也是很容易的:
[javascript] view plain copy  
  1. promiseB = promiseA.then(function(result) {  
  2.   return result + 1;  
  3. });  
  4.    
  5. // promiseB 將會在處理完 promiseA 之後立刻被處理,  
  6. // 並且其  value值是promiseA的結果增加1  
我們可以建立任意長度的promise鏈;因為一個promise可以被另一個promises處理(進一步延遲解決完成時間),所以在promise鏈上的任意一點進行 暫停/延遲解決 都是可行的。 這使得實現功能強大的APIs 成為現實,例如  $http 的響應攔截器。
Kris Kowal‘s Q 與 $q 之間的區別主要區別有兩點:
  • Angular中的$q 整合了 ng.$rootScope.Scope  Scope模型觀察機制,這意味著對models 的解決或拒絕速度將會更快,避免不必要的瀏覽器重繪(會導致UI閃爍)。
  • Q 比 $q擁有更多的功能特性,但帶來的是代碼位元組數的增加。 $q 很輕量級,但包含了一般非同步任務所需的所有重要功能。
     測試 [javascript] view plain copy  
  1. it(‘should simulate promise‘, inject(function($q, $rootScope) {  
  2.   var deferred = $q.defer();  
  3.   var promise = deferred.promise;  
  4.   var resolvedValue;  
  5.    
  6.   promise.then(function(value) { resolvedValue = value; });  
  7.   expect(resolvedValue).toBeUndefined();  
  8.    
  9.   // 類比 promise 的 resolving  
  10.   deferred.resolve(123);  
  11.   // 注意 ‘then‘ function 不是同步調用的.  
  12.   // 因為我們想要  promise API 一直是非同步(async),  
  13.   // 不管是在同步調用還是非同步呼叫中都是如此.  
  14.   expect(resolvedValue).toBeUndefined();  
  15.    
  16.   // 使用 $apply()將 promise resolution 傳遞到 ‘then‘ functions .  
  17.   $rootScope.$apply();  
  18.   expect(resolvedValue).toEqual(123);  
  19. }));  
依賴關係 | Dependencies $rootScope 

方法 | Methods all(promises)結合多個promises為單個promise,在所有輸入的promise都處理之後,組合之後的promise才會處理完成。
  • 參數: promises
  • 類型: Array.<Promise>/Object.<Promise>
  • 描述: promises的數組或者引用
  • 返回: Promise 返回單個的 promise,將與一個數組解決/散列值, 每個值對應於在相同的索引/關鍵的承諾 承諾 /散列數組。 如果任何承諾解決排斥,這產生的承諾將被拒絕 拒絕相同的值。
defer()建立一個 遞延 對象代表一個將來完成任務。
  • 返回  Deferred 返回一個新執行個體的Deferred。
reject(reason)建立一個指定拒絕原因的promise. 此api應該用於在一個promises鏈中進行拒絕。 如果你正在處理promise 鏈中的最後一個promise,你不需要擔心。

把  deferreds/promises 與我們熟悉的的 try/catch/throw行為進行對比,可以認為 reject 相當於 JavaScript 中的throw 關鍵字。 這也意味著如果你通過一個 promise 的 error回調,  “catch”了一個錯誤 ,你想要指明當前的承諾已經執行出錯了,就必須重新拋出一個“附帶了錯誤資訊,拒絕通過的reject” 。
[javascript] view plain copy  
  1. promiseB = promiseA.then(function(result) {  
  2.   // success: 此處可以執行某些操作,然後直接使用原有的result,  
  3.   // 或者對result進行操作,來處理接下來的promiseB  
  4.   return result;  
  5. }, function(reason) {  
  6.   // error: handle the error if possible and  
  7.   //        resolve promiseB with newPromiseOrValue,  
  8.   //        否則轉向拒絕 promiseB 的分支  
  9.   if (canHandle(reason)) {  
  10.    // 處理錯誤和恢複  
  11.    return newPromiseOrValue;  
  12.   }  
  13.   return $q.reject(reason);  
  14. });  
  • 參數: reason
  • 類型: *
  • 描述: Constant, message, exception 或代表拒絕原因的 object。
  • 返回: Promise    返回一個promise ,已經因為 reason 而被拒絕了 。
when(value)將一個對象(可能是value 或  [第三方]then-able promise) 封裝為一個 $q promise。 這在你不確定所處理的對象是否是一個promise 時是很有用的,有可能該對象來自於一個不被信任的源頭。
  • 參數: value
  • 類型: *
  • 描述: promise 的值
  • 返回 Promise    根據傳入的值/或promise 返回一個封裝後的 promise

$q -- AngularJS中的服務(理解)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.