我正在使用breeze和knockout编写一个带有typescript的SPA。
我想做的是创建一个启动管理器,它可以执行启动网站所需的必要步骤(例如读取配置json、下载odata元数据、初始化微风元数据存储等)。
我创建了以下内容来表示启动序列中的每个步骤:
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!") });
但我想创建某种管理器对象,它不知道需要多少步骤。它只负责构建一个promise数组并按顺序执行它们,同时能够检测错误(可能是失败promise中的错误)并中止序列。
管理器将具有某种包含LauncherProgressItem步骤的集合。然后,我希望建立一个基于该集合内容的承诺链。
我已经研究了一段时间,但似乎真的不知道如何用Q来做这件事。我看过一些例子等,但我真的不明白它是如何工作的。
有人对如何实现这一目标有什么建议吗?
更新:我将尝试澄清我试图实现的目标:我的LauncherProgressItem封装了一个lambda函数和一些绑定到视图的状态信息。这就是我使用这些的原因,但这与我实际在挣扎的事情有点无关。
假设我有一个类,它包含一个lambda数组。这个类有一个方法,它将使用Q按顺序运行所有这些lambas,在出现错误时中止。确切地说,我将实现以下代码:
Q.fcall(doSomething).then(doSomethingElse).fail(reportError);
然而,在这种情况下,doSomething
和doSomethingElse
驻留在函数数组中,而不是固定数量的步骤中。这是因为我希望它是可重用的,即能够根据手头的任务在多个场景中运行。因此,我希望避免对要运行的函数链进行硬编码。
对不起,我不知道typescript,但我认为上面的评论线程进行得不太好,所以下面是您在纯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);
}