使用Q动态运行一系列承诺

时间:2014-09-13 11:41:01

标签: javascript knockout.js typescript promise q

我正在使用breeze和knockout编写带有打字稿的SPA。

我想要做的是创建一个启动管理器,它可以执行甚至启动站点所需的必要步骤(例如,读取配置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!") });

但是我想创建某种管理器对象,它并不真正知道需要多少步骤。它只负责构建一个promises数组并按顺序执行它们,同时能够检测错误(可能是在失败承诺中)并中止序列。

管理器将包含某种包含LauncherProgressItem步骤的集合。然后,我希望根据该集合的内容构建一系列承诺。

我现在已经看了一段时间,但似乎无法真正了解如何用Q做这个。我已经看到了一些例子等但我真的不明白它是如何工作的。

任何人都有关于如何实现这一目标的任何建议?

更新:我将尝试澄清我想要实现的目标:我的LauncherProgressItem包含一个lambda函数和一些状态信息,我将其绑定到我的视图。这就是我使用这些的原因,但这与我实际上正在努力的事情无关。

所以我假设我有一个包含lambda数组的类。这个类有一个方法,它将使用Q顺序运行所有这些lambas,在出错时中止。正是我用以下代码实现的目标:

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

但是,在这种情况下,doSomethingdoSomethingElse驻留在一系列函数中,而不是固定数量的步骤。这是因为我希望它可以重复使用,即能够根据手头的任务在多个场景中运行。所以我想避免硬编码运行的函数链。

1 个答案:

答案 0 :(得分: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);
}