Нокаут единой наблюдаемой с несколькими подписками - PullRequest
0 голосов
/ 29 мая 2019

Я унаследовал приложение, написанное с использованием Knockout для пользовательского интерфейса, и мне интересно, каков эффект от нескольких подписок на одно наблюдаемое свойство?

У меня есть наблюдаемая, которая имеет 2 подписки. Войдя в консоль, я вижу, что обе подписки срабатывают одна за другой.

Используя следующий пример: (для краткости это очень урезано, в полном коде есть много логики, часть из которых дублируется)

self.VisitDate = ko.observable();

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

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

Я думал, что должен увидеть какую-то ошибку из-за множественных подписок, но, кажется, все работает нормально, но я не могу найти четкого объяснения, почему это нормально делать

Я просто пытаюсь выяснить следующее:

Нормально и приемлемо ли иметь несколько подписок на одну наблюдаемую? Есть ли какое-то основное влияние на это, то есть условия гонки? Нужно ли когда-либо иметь несколько подписок, чтобы достичь чего-то, чего нельзя достичь за одну подписку?

Я понимаю, что это может быть немного застенчиво в деталях, но на самом деле я просто пытаюсь понять, как нокаут делает вещи под прикрытием, чтобы понять, стоит ли мне пытаться реорганизовать этот код или нет.

1 Ответ

0 голосов
/ 29 мая 2019

Шаблон наблюдатель / наблюдаемый проект допускает несколько наблюдателей / подписок. Короче говоря, дизайн шаблона:

  1. Отмените изменение от последствий изменения.
  2. Разрешить любые и произвольные эффекты, вытекающие из изменения.

Итак, Knockout делает это через свои наблюдаемые.

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>

Не нужно беспокоиться о состоянии гонки, потому что ваш код будет выполняться в одном потоке , так что он в значительной степени гарантированно будет детерминированным, если вы явно не выберете мульти-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>

Так что, это было бы плохой практикой. Было бы лучше избегать, если это возможно. Если вы не можете гарантировать порядок подписок - в приведенном выше примере я добавляю подписки одну за другой, что гарантирует их отображение в порядке их добавления. Но у вас может быть код, который добавляет подписки условно или в разных частях приложения, и в этом случае сложно контролировать этот порядок.

...