【问题标题】:Dynamically run a sequence of promises using Q使用 Q 动态运行一系列 Promise
【发布时间】:2014-11-07 11:48:27
【问题描述】:

我正在使用微风和淘汰赛编写带有打字稿的 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);

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

【问题讨论】:

  • 为什么你需要所有这些LauncherProgressItems - 只使用承诺来处理操作顺序有什么问题?无论如何,这就是承诺的作用..
  • 您可能会对this 感兴趣。这篇文章实际上是关于各种“反模式”的罪行,你没有犯下任何一个(好吧,我们都不知道 :)),但是标题为“The Collection Kerfuffle”下的第二个“好”模式至少可能会有所帮助你更好地理解这个问题。对模式进行一些轻微的调整甚至可以提供解决方案。
  • @BenjaminGruenbaum 我的问题是如何动态链接承诺。你问我“为什么不直接使用 Promise”,尽管我已经明确表示“我已经看过一些示例等,但我并不真正理解它是如何工作的。”还因为我不是每天都来这里而对我投反对票?在周末,不少于!干杯。我将工作项目包装在类中,以便我可以将它们绑定到我的启动屏幕。可能有数百万种方法可以做到这一点,但我在这里征求意见。您为什么不尝试建设性地提供帮助?
  • @havardhu 我正在尝试建设性地提供帮助,否决票是提示您解决问题的一种方式。对我来说最简单的事情就是不要发表评论,这会使您的问题在几天内自动删除。我很抱歉,如果它看起来很苛刻,但这是因为我想帮忙。你能澄清一下你实际上想要做什么吗?对我有用的是从不了解我的代码的人的角度阅读本文。

标签: javascript knockout.js typescript promise q


【解决方案1】:

对不起,我不知道打字稿,但我认为上面的评论线程不太顺利,所以这是你在普通 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);
}

【讨论】:

    猜你喜欢
    • 2018-08-22
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多