淺談Angular的$q, defer, promise

風靈使發表於2019-04-05

1. $q

$qAngular的一種內建服務,它可以使你非同步地執行函式,並且當函式執行完成時它允許你使用函式的返回值(或異常)。

2. defer

defer的字面意思是延遲,$q.defer() 可以建立一個deferred例項(延遲物件例項)。

deferred 例項旨在暴露派生的Promise 例項,以及被用來作為成功完成或未成功完成的訊號API,以及當前任務的狀態。這聽起來好複雜的樣子,總結$q, defer, promise三者之間的關係如下所示。

var deferred = $q.defer();  //通過$q服務註冊一個延遲物件 deferred
var promise = deferred.promise;  //通過deferred延遲物件,可以得到一個承諾promise,而promise會返回當前任務的完成結果

defer的方法:

  1. deferred.resolve(value) 成功解決(resolve)了其派生的promise。引數value將來會被用作promise.then(successCallback(value){...}, errorCallback(reason){...}, notifyCallback(notify){...})successCallback函式的引數。

  2. deferred.reject(reason) 未成功解決其派生的promise。引數reason被用來說明未成功的原因。此時deferred例項的promise物件將會捕獲一個任務未成功執行的錯誤,promise.catch(errorCallback(reason){...})。補充一點,promise.catch(errorCallback)實際上就是promise.then(null, errorCallback)的簡寫。

  3. notify(value)更新promise的執行狀態(翻譯的不好,原話是provides updates on the status of the promise's execution)

defer的小例子:

function asyncGreet(name) {
  var deferred = $q.defer();  //通過$q.defer()建立一個deferred延遲物件,在建立一個deferred例項時,也會建立出來一個派生的promise物件,使用deferred.promise就可以檢索到派生的promise。

  deferred.notify('About to greet ' + name + '.');  //延遲物件的notify方法。

  if (okToGreet(name)) {
    deferred.resolve('Hello, ' + name + '!');  //任務被成功執行
  } else {
    deferred.reject('Greeting ' + name + ' is not allowed.');  //任務未被成功執行
  }

  return deferred.promise;  //返回deferred例項的promise物件
}

function okToGreet(name) {
  //只是mock資料,實際情況將根據相關業務實現程式碼
  if(name == 'Superman') return true;  
  else return false;
}

var promise = asyncGreet('Superman');  //獲得promise物件
//promise物件的then函式會獲得當前任務也就是當前deferred延遲例項的執行狀態。它的三個回撥函式分別會在resolve(), reject() 和notify()時被執行
promise.then(function(greeting) {
  alert('Success: ' + greeting);
}, function(reason) {
  alert('Failed: ' + reason);
}, function(update) {
  alert('Got notification: ' + update);
});

3. promise

當建立一個deferred例項時,promise例項也會被建立。通過deferred.promise就可以檢索到deferred派生的promise

promise的目的是允許interested parties 訪問deferred任務完成的結果。

按照CommonJS的約定,promise是一個與物件互動的介面,表示一個動作(action)的結果是非同步的,而且在任何給定的時間點上可能或不可能完成。(這句話好繞口,我的理解是promise相當於一個承諾,承諾你這個任務在給定的時間點上可能會完成,也可能完成不了。如果完成了那就相當於resolve, 如果未完成就相當於reject。不知道這樣理解對不對?)

promise 的方法:

  1. then(successCallback, errorCallback, nitifyCallback) 根據promiseresolve/reject,或將要被resolve/reject,呼叫successCallback/errorCallback
  2. catch(errorCallback) then(null, errorCallback)的縮寫。
  3. finally(callback, notifyCallback)

補充說明:

promise.then()會返回一個新的衍生promise,形成promise鏈。例如:

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

// promiseB will be resolved immediately after promiseA is resolved and its value
// will be the result of promiseA incremented by 1

相關文章