使用 q 服務的 Angular 承諾

$q 是一個內建服務,它有助於執行非同步函式並在完成處理時使用它們的返回值(或異常)。

$q$rootScope.Scope 模型觀察機制整合,這意味著更快地將解析度或拒絕傳播到模型中,避免不必要的瀏覽器重繪,這將導致 UI 閃爍。

在我們的例子中,我們呼叫我們的工廠 getMyData,它返回一個 promise 物件。如果物件是 resolved,則返回一個隨機數。如果是 rejected,它會在 2 秒後返回拒絕並顯示錯誤訊息。

在 Angular 工廠

function getMyData($timeout, $q) {
  return function() {
    // simulated async function
    var promise = $timeout(function() {
      if(Math.round(Math.random())) {
        return 'data received!'
      } else {
        return $q.reject('oh no an error! try again')
      }
    }, 2000);
    return promise;
  }
}

在呼叫中使用 Promise

angular.module('app', [])
.factory('getMyData', getMyData)
.run(function(getData) {
  var promise = getData()
    .then(function(string) {
      console.log(string)
    }, function(error) {
      console.error(error)
    })
    .finally(function() {
      console.log('Finished at:', new Date())
    })
})

要使用 promises,請將 $q 注入依賴項。我們在 getMyData 工廠注入了 $q

var defer = $q.defer();

通過呼叫 $q.defer() 構造一個新的 deferred 例項

延遲物件只是一個公開 promise 的物件,以及解析該 promise 的相關方法。它使用 $q.deferred() 函式構建,並暴露出三種主要方法:resolve()reject()notify()

  • resolve(value) - 使用值解析派生的 promise。
  • reject(reason) - 拒絕派生的承諾。
  • notify(value) - 提供有關承諾執行狀態的更新。在承諾被解決或拒絕之前,可以多次呼叫此方法。

屬性

通過 promise 屬性訪問關聯的 promise 物件。promise - {Promise} - 與此延遲相關聯的 promise 物件。

建立延遲例項時會建立一個新的 promise 例項,並可以通過呼叫 deferred.promise 來檢索。

promise 物件的目的是允許感興趣的各方在完成時訪問延遲任務的結果。

承諾方法 -

  • then(successCallback, [errorCallback], [notifyCallback]) - 無論何時或將要解決或拒絕承諾,只要結果可用,就會非同步呼叫其中一個成功或錯誤回撥。使用單個引數呼叫回撥:結果或拒絕原因。另外,在解決或拒絕承諾之前,可以將通知回撥呼叫零次或多次以提供進度指示。

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

  • finally(callback, notifyCallback) - 允許你觀察承諾的履行或拒絕,但是在不修改最終值的情況下這樣做。

承諾最強大的功能之一是將它們連結在一起的能力。這允許資料流過鏈並在每一步被操作和變異。以下示例演示了這一點:

例 1:

// Creates a promise that when resolved, returns 4.
function getNumbers() {

  var promise = $timeout(function() {
    return 4;
  }, 1000);
  
  return promise;
}

// Resolve getNumbers() and chain subsequent then() calls to decrement
// initial number from 4 to 0 and then output a string.
getNumbers()
  .then(function(num) {
      // 4
      console.log(num);
      return --num;
  })
  .then(function (num) {
      // 3
      console.log(num);
      return --num;
  })
   .then(function (num) {
      // 2
      console.log(num);
      return --num;
  })
  .then(function (num) {
      // 1
      console.log(num);
      return --num;
  })
  .then(function (num) {
      // 0
      console.log(num);
      return 'And we are done!';
  })
  .then(function (text) {
      // "And we are done!"
      console.log(text);        
  });