Posts match “ promise ” tag:

用 ngQueue 來完成需要排隊的非同步工作

$q promise 是使用 AngularJS 時相當重要的一環,熟悉並活用之後可以讓許多原本看似較雜亂的 event-base 程式碼看起來謹然有序(當然也不是所有的 event-base 程式都適合使用 promise 來實現)。

排隊的需求

有時候我們會碰到一些特別的情況:

一段一段的動作是依序進行,但觸發的時候卻又是一次性的(比如說在一個 loop 中一次排定 10 個非同步的工作,需要依序執行)。

用程式碼表示大概是這樣:

var taskIds = [1, 2, 3, 4, 5];

angular.forEach(taskIds, function (taskId) {

  // 以 $http 為例
  $http.get('/someUrl', {params: {taskId: taskId}});

});

console.log('工作順利完成!');

然而我們真正想做的事情是這樣:

$http.get('/someUrl', {params: {taskId: 1}})
.then(function () {
  return $http.get('/someUrl', {params: {taskId: 2}});
})
.then(function () {
  return $http.get('/someUrl', {params: {taskId: 3}});
})
.then(function () {
  return $http.get('/someUrl', {params: {taskId: 4}});
})
.then(function () {
  return $http.get('/someUrl', {params: {taskId: 5}});
})
.then(function () {
  console.log('工作順利完成!');
});

在上面的例子中,工作只有五項所以固然可以自己打一打程式碼解決,一般來說碰到的情況會有下面的困境:

  • 工作項目數未知(為動態的或為參數)
  • 同時可以進行的工作數不只一項(以上面為例即 1, 2 可以同時進行,而 3, 4 可以同時進行,最後再單獨執行 5 即可)
Read on

一個 NPC 的故事 - Case Study of Promise

昨天在某固定會逛的 Facebook 社群看到有人問了 JavaScript 的問題,需求大致上是:

想要建立一個 NPC 的物件,對外提供幾個 API 來使用

  1. OnTrigger() - 讓 NPC 出現在畫面上
  2. OnDialog() - NPC 秀出對話框,對話框內有一個確認鈕
  3. OnWalk() - 若對話框曾經開啟並關閉之後,將 NPC 移動至某特定位置

希望的執行方法是(連續動作):

  1. OnTrigger();
  2. OnDialog();
  3. OnWalk();

很明顯的主要的困難處在於

OnDialog()OnWalk()是照順序執行,要如何能夠讓實際的OnWalk()內容在OnDialog()有了某種結果之後才執行?

Read on

三個不要再用 jQuery Promise 的理由

Update 2016/04/05 20:27
話說 beta 中的 jQuery 3.0 確定 Promise 的部分會是相容於 Promises/A+,到時候出了正式版本可以開心升級!


其實不要用 jQuery promise 這回事兒,時有所聞,最主要的原因是其實它實作的內容跟外面大部分的 Promise library (Promises/A+)都不一樣。

所以很多人覺得 jQuery 的 Promise 只是名為 Promise 的「某種東西」,並不是真正的 Promise。

想了解詳情可以看一下 2012 年的這篇文章
You're Missing the Point of Promises

然而我一直不以為意。

到這個星期我才切身的實際體會不要用的原因,這邊列出三點,應該是比較容易碰到的情況。

1. 面對靜態結果,$.when() 不會以非同步的方式產出 resolved promise

這個我想應該很多人已經有經驗 XD

舉例如下:

// 期待中,結果會是以 async 的方式取得

function xhrGet(something) {
    if (cache) {
        return $.when(cache);
    }
    return $.get(something);
}

/**
 * 在送出 XHR request 之後清空頁面,取得 response 之後重繪頁面
 * 
 * 沒有 cache - 正常運作
 *   有 cache - 在 `renderPage()` 之後才 `clearPage()`,頁面就沒了
 */
xhrGet(...).then(function (res) {
    renderPage(res);
});
clearPage();

那麼我們實際來確認一下大家的情況,下面用了三家的 library 來做測試:
(其中 Promise 的部分是用 polyfill 的方式,如果你的瀏覽器有原生支援就會用瀏覽器內建的)

Read on