代码之家  ›  专栏  ›  技术社区  ›  havardhu

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

  •  0
  • havardhu  · 技术社区  · 10 年前

    我正在写一份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!") });
    

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

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

    我已经研究了一段时间,但似乎无法真正理解如何使用Q来实现这一点。

    有人对如何实现这一目标有什么建议吗?

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

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

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

    然而,在这种情况下 doSomething doSomethingElse 驻留在函数数组中,而不是固定数量的步骤中。这是因为我希望它是可重用的,即能够根据手头的任务在多个场景中运行。因此,我希望避免对要运行的函数链进行硬编码。

    1 回复  |  直到 10 年前
        1
  •  2
  •   Milimetric    10 年前

    抱歉,我不知道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);
    }