2014-09-13 17 views
0

我正在使用微風和淘汰賽來編寫一個使用打字機的SPA。動態運行一系列使用Q的承諾

我想要做的是創建啓動管理器,它可以執行甚至啓動站點所需的必要步驟(例如,讀取配置json,下載odata元數據,初始化breeze元數據存儲等)。

我創建了以下代表在啓動順序的每一步:

export enum LauncherProgressStatus { 
    Ready, 
    InProgress, 
    Success, 
    Failed, 
    Aborted 
} 

export class LauncherProgressItem { 
    public status: KnockoutObservable<LauncherProgressStatus> = ko.observable<LauncherProgressStatus>(); 
    public description: KnockoutObservable<String> = ko.observable<String>(); 

    public statusText: KnockoutComputedFunctions<String> = ko.computed<String>(() => { 
     return LauncherProgressItem.getStatusText(this.status()); 

    }); 

    public start() { 
     this.action(this); 
    } 

    constructor(descriptionText: String, 
       public action: (arg: LauncherProgressItem) => Boolean) { 
     this.status(LauncherProgressStatus.InProgress); 
     this.description(descriptionText); 
    } 

    public static getStatusText(status: LauncherProgressStatus) : String { 
     switch (status) { 
      case LauncherProgressStatus.Ready: 
       return "Ready"; 
      case LauncherProgressStatus.InProgress: 
       return "In progress"; 
      case LauncherProgressStatus.Success: 
       return "Success"; 
      case LauncherProgressStatus.Aborted: 
       return "Aborted"; 
      default: 
       return "Failed"; 
     } 
    } 
} 

TL; DR我創造這樣的代碼的每一步:

var item1 = new launcher.LauncherProgressItem("Loading configuration...", (item: LauncherProgressItem) => { 
    cfgMgr.setConfigurationFromFile("config.json?bust=" + (new Date()).getTime()); 
    return true; 
}); 

現在的問題:我想利用這個來創建一個使用Q的承諾鏈。我可以手動做到這一點,即

q.fcall(() => item1.action(item1)) 
    .then(() => item2.action(item2)) 
    .fail((r) => { console.log("Many whelps, HANDLE IT!") }); 

但我想創建某種不知道需要多少步驟的管理對象。它將負責構建一系列承諾並按順序執行它們,同時能夠檢測到錯誤(假設爲失敗承諾)並中止序列。

管理器將擁有某種包含LauncherProgressItem步驟的集合。然後我打算根據該集合的內容構建一系列承諾。

我一直在看這一段時間,但似乎不能真正讓我的頭瞭解如何使用Q做到這一點。我見過一些例子等,但我真的不明白它是如何工作的。

任何人有任何建議如何實現這一目標?

更新:我會盡力澄清什麼,我努力實現:我LauncherProgressItem包裝lambda函數和我將綁定到我的觀點一些狀態信息。這就是爲什麼我使用這些,但這與我實際上正在掙扎的東西無關。

所以我們假設我有一個包含lambda數組的類。這個類有一個方法,它將使用Q按順序運行所有這些lambas,在錯誤時中止。正是我將用下面的代碼實現:

Q.fcall(doSomething).then(doSomethingElse).fail(reportError); 

然而,在這種情況下doSomethingdoSomethingElse駐留在函數數組,而不是步驟的固定數量。這是因爲我希望它可以重複使用,即能夠根據手頭的任務在多種情況下運行。所以我想避免硬編碼的功能鏈運行。

+1

爲什麼你需要所有這些'LauncherProgressItem' s - 爲操作順序使用承諾有什麼問題?這就是承諾無論如何.. – 2014-09-13 12:44:51

+0

你可能會發現[this](http://taoofcode.net/promise-anti-patterns/)是有趣的。這篇文章實際上是關於各種「反模式」的罪行,其中沒有一個是你所犯下的(當然,我們都不知道:)),但標題「The Collection Kerfuffle」下的第二個「好」模式可能至少有助於你更好地理解這個問題。這種模式的一些適應性可能會提供一個解決方案。 – 2014-09-13 13:43:57

+2

可能重複的[如何在Javascript中按順序運行Promise?](http://stackoverflow.com/q/18386753/1048572) – Bergi 2014-09-13 17:48:23

回答

2

對不起,我不知道打字稿,但我認爲評論跟帖上面是不會很好,所以這裏就是您請求的純JS的功能:

function runInSequence (functions) { 
    if (!functions || !functions.length) { 
     return; 
    } 

    var nextPromise = Q.fcall(functions[0]); 

    functions.slice(1).forEach(function (f) { 
     nextPromise = nextPromise.then(f); 
    }); 

    nextPromise.fail(yourErrorHandler); 
}