【问题标题】:Knockout single observable with multiple subscriptions具有多个订阅的淘汰单个 observable
【发布时间】:2019-10-15 05:21:46
【问题描述】:

我继承了一个使用 Knockout 为 UI 编写的应用程序,我很好奇对单个可观察属性进行多个订阅的效果是什么?

我有一个有 2 个订阅的 observable。通过登录控制台,我可以看到两个订阅一个接一个地被触发。

使用以下示例:(为简洁起见,在完整代码中有很多逻辑,其中一些是重复的)

self.VisitDate = ko.observable();

self.VisitDate.subscribe(function (newValue) {
    self.ListItemRemoved(removed);
});   

self.VisitDate.subscribe(function (newValue) {
    self.Basket.VisitDate(newValue);
});

我在想我应该看到某种错误,因为有多个订阅,但一切似乎都工作正常,但我找不到任何明确的解释为什么可以这样做?

我只是想找出以下内容:

对单个 observable 进行多个订阅是否正常且可以接受? 这样做是否有任何潜在的影响,即可能存在竞争条件? 是否真的需要多次订阅才能实现单次订阅无法实现的目标?

我很欣赏这可能有点害羞,但我真的只是想了解淘汰赛是如何在幕后做事的,看看我是否应该重构这段代码。

【问题讨论】:

  • observer/observable pattern设计允许多个订阅。整个想法是首先将更改及其效果解耦,然后使您能够拥有任何数量的效果。 KO在这方面并不奇怪。 “竞争条件”几乎不是问题 - JS 将在单个线程中运行您的代码,并且 observable 将一一通知每个观察者。
  • 我明白了,因为它们在 1 个线程中,它们将一个接一个地执行,因此第二个订阅可以对第一个订阅的执行导致的更改采取行动,我是否理解正确?

标签: javascript knockout.js observable subscribe


【解决方案1】:

observer/observable design pattern 确实允许多个观察者/订阅者。简而言之,设计模式的目的是:

  1. 将变化与变化的影响分离。
  2. 允许任何和任意的影响源于更改。

所以,Knockout 通过它的 observables 做到这一点。

var observable = ko.observable("a");

observable.subscribe(function(newValue) {
  console.log("observer 1", newValue)
});

observable.subscribe(function(newValue) {
  console.log("observer 2", newValue)
});

observable.subscribe(function(newValue) {
  console.log("observer 3", newValue)
});

observable("b");
observable("c");
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

没有真正需要担心的竞争条件,因为your code will be run in a single thread,所以它几乎可以保证是确定性的,除非您明确选择加入某种multi-threadedness

无论如何,观察者通常也不会固有地调用多个线程,因为订阅者更新功能通常会采取以下形式:

for (subscriber of this.subscribers) {
  subscriber.update(this.value);
}

话虽如此,您可能会遇到问题,但前提是订阅者依赖于共享状态并且您无法保证或知道每个订阅的添加顺序。在这种情况下,您可以根据订阅的顺序获得不同的结果。简单演示:

var observable = ko.observable("a");

var sharedState = "";

observable.subscribe(function(newValue) {
  //append to the shared state
  sharedState += newValue;
  console.log("observer 1", sharedState);
});

observable.subscribe(function(newValue) {
  //double up the shared state
  sharedState += sharedState;
  console.log("observer 2", sharedState);
});

observable("b");
observable("c");
observable("d");
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

var observable = ko.observable("a");

var sharedState = "";


observable.subscribe(function(newValue) {
  //double up the shared state
  sharedState += sharedState;
  console.log("observer 2", sharedState);
});

observable.subscribe(function(newValue) {
  //append to the shared state
  sharedState += newValue;
  console.log("observer 1", sharedState);
});

observable("b");
observable("c");
observable("d");
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

所以,这将是一个不好的做法。如果可能的话,最好避免。除非您可以保证订阅的顺序 - 在上面的示例中,我一个接一个地添加订阅,以保证它们按添加顺序显示。但是您的代码可能有条件地或在应用程序的不同部分添加订阅,在这种情况下,很难控制该顺序。

【讨论】:

    猜你喜欢
    • 2016-06-27
    • 2018-06-05
    • 2016-01-27
    • 1970-01-01
    • 2019-03-28
    • 2017-01-30
    • 2016-06-09
    • 2017-03-02
    • 1970-01-01
    相关资源
    最近更新 更多