【发布时间】:2016-04-19 20:51:24
【问题描述】:
我知道这个问题已经被问过好几次了,但我认为 SO 中的问答都没有提到这个问题中解释的场景。
我有一个 JavaScript 组件(它是一个 KO 组件,但没关系)。根据该组件中的某些操作,它可以异步加载子组件的几个不同版本。这可能会发生多次。 IE。本来它可以加载孩子A,然后用孩子B替换它等等。
主组件需要运行子组件的一些功能。为此,它将一个名为 registerApi 的函数传递给子组件构造函数。这样,当子组件加载完成时,它会调用registerApi。为了避免父组件在加载子组件之前调用 API,registerApi 以这种方式使用 promise:
var childApiDeferred = $.Deferred();
var childApiPromise = childApiDerred.promise();
var registerApi = function(api) {
childApiDeferred.resolve(api);
};
这样,每当主组件需要调用子组件的 API 时,它都是通过 Promise 来完成的,这样,它只会在子组件加载完成并注册其 API 时运行。子组件 API 中的方法调用如下:
childApiPromise.then(function(api) { api.method(); })
到目前为止,一切都很好。问题是在某个时间点,子组件可能会被一个新组件交换。此时,我需要 reset 将 deferred 设置为未解析状态,这样,如果主组件尝试调用 API,它必须等到新组件已加载并已注册它的 API。
我还没有看到任何可重置延迟的实现,也没有任何其他可以解决这个问题的东西。我发现的唯一解决方案,并且使代码更加复杂(我没有展示它)是,每当一个新组件开始加载时,我创建一个新的延迟,并公开新延迟的承诺,以便调用:
childApiPromise.then(function(api) { api.method(); })
总是指新的承诺。 (正如我所说,这会使代码复杂化)。
当然,对于第一个子组件,deferred/promise 就像一个魅力,但是,我正在寻找类似 deferred 的东西,它可以是未解决的,这样我就可以在新组件开始加载时取消它。
是否有一种可重置的延迟或任何其他 JavaScript 模式允许存储回调并在新功能准备好时调用它们?有没有可能以任何方式实现它?
组件交换是如何发生的?
正如我在评论中被问到的那样,我会解释它,尽管我认为它与这个 Q 无关。
我将 Knockout 与组件一起使用。我有一个主组件,它有一个子组件。当我更改包含组件名称的属性时,KO 基础结构会自动交换子组件。此时我知道我必须“暂停”对子组件 API 的调用,因为正在加载一个新的子组件,而此时 API 不可用。子组件异步加载并接收一系列参数,包括来自主组件的registerApi回调。当子组件完成加载后,它会调用registerApi 将其API 暴露给父组件。 (附带说明一下,所有子组件都向主组件公开相同的功能,但实现方式不同)。
所以,这是交换组件时发生的步骤:
- 主组件新建一个deferred“childApiDeferred”,未解决
- 主组件设置新子组件的名称,以便ko基础架构交换子组件,并将
registerApi回调传递给子组件 - 子组件是异步加载的,加载完成后调用
registerApi,也解决了deferred - 父组件可以通过 Promise 安全地调用子 API,因为在解决之前它们不会被执行
每次删除和创建一个新的承诺都可以正常工作。问题是这需要编写大量代码以确保正确完成,并且所有代码都使用新的,而不是旧的,延迟或承诺。如果 promise where resettable 你只需要重置并解决它:两行简单的代码。
【问题讨论】:
-
您正在寻找玻璃钢。
-
@Bergi 谢谢你的建议。我找到了开菲尔和培根。我应该检查这些还是您更喜欢任何其他选项?
-
一切似乎都取决于“子组件可以被新组件交换”的含义。这实际上意味着什么?我们可以看看进行交换的代码吗?
-
@JotaBe:是的,我想让你看看这些,以获得一个想法。还有很多其他的,Rx.js 也很流行。我不喜欢任何特定的。
-
Knockout 已经由 observables 提供支持——您可能只想使用计算的 observable 并通过它运行更新。
标签: javascript promise deferred