2013-08-01 3 views
36

Есть ли способ игнорировать подписчиков при изменении значения наблюдаемого. Id нравится изменять значение наблюдаемого, но не выполнять его для подписчиков с knockout.jsИзменение наблюдаемых, но не уведомляющих подписчиков в knockout.js

+0

Как RP указывает, что это обычно не является хорошей идеей. Каков ваш прецедент? Возможно, есть * конкретный * абонент, которого вы не хотите уведомлять? – Tyrsius

+0

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

ответ

73

Обычно это невозможно или желательно, так как это потенциально позволяет избежать сбоев в цепочках зависимостей. Использование удлинителя дроссельной заслонки обычно является хорошим способом ограничить количество уведомлений, получаемых зависимостями.

Однако, если вы действительно хотите это сделать, то одним из вариантов было бы перезаписать функцию notifySubscribers на наблюдаемом и проверить флажок.

Вот это расширение, добавляющее эта функциональность для наблюдаемого:

ko.observable.fn.withPausing = function() { 
    this.notifySubscribers = function() { 
     if (!this.pauseNotifications) { 
      ko.subscribable.fn.notifySubscribers.apply(this, arguments); 
     } 
    }; 

    this.sneakyUpdate = function(newValue) { 
     this.pauseNotifications = true; 
     this(newValue); 
     this.pauseNotifications = false; 
    }; 

    return this; 
}; 

Вы бы добавить это к наблюдаемым как:

this.name = ko.observable("Bob").withPausing(); 

Тогда вы бы обновить его без уведомлений, выполнив:

this.name.sneakyUpdate("Ted"); 
+2

+1 для дросселирования. Я хотел бы избегать многократного запуска вычислений при установке нескольких наблюдаемых объектов, от которых зависело вычисление. Результат: скорость ++ – billy

+3

В этом случае наиболее удобно просто приостанавливать уведомления, чтобы вы могли обновлять все ваши наблюдаемые и активировать подписки только в самом конце (сообщение ryan http://www.knockmeout.net/2011/04/pausing -notifications-in-knockoutjs.html) –

+2

Хороший ответ. Я думаю, что «sneakyUpdate» может быть лучше назван «poke», поскольку KO предоставляет встроенный метод «peek», который действительно читается. «poke» будет записываемой версией «peek». – raider33

5

Мне нравится решение предоставлено @RP Niemeyer, когда все подписчики должны быть проигнорированы. Однако для моего случая у меня есть наблюдаемый с 2-сторонними привязками на элементе управления Select. При использовании @RP Niemeyer элемент управления Select не обновляется. Поэтому мне действительно нужен был способ отключить конкретных наблюдателей, не все. Вот обобщенное решение для этого случая.

Добавить методы расширения для «тихой» подписки и «тихой» записи.

ko.observable.fn.ignorePokeSubscribe = function (callback, thisValue, event){ 
    var self = this; 
    this.subscribe(function(newValue) { 
     if (!self.paused) 
      callback(newValue); 
    }, thisValue, event); 
    return this; 
}; 
ko.observable.fn.poke = function (newValue) { 
    this.paused = true; 
    var result = this(newValue); 
    this.paused = undefined; 
    return result; 
}; 

Вы подписались бы наблюдаемым как:

this.name = ko.observable("Bob"); 
this.name.ignorePokeSubscribe(function(newValue) { /* handler */ })); 

Тогда вы бы обновить его без специальных уведомлений, выполнив:

this.name.poke("Ted"); // standard subscribers still get notified 
+2

Я не думаю, что это означает, что вы думаете, что это значит. –

+1

Спасибо @Barry Franklin, я исправил орфографию до «тишины» – raider33

+0

Спасибо, v полезен, чтобы иметь возможность подавлять уведомления для изменений кода, только то, что мне нужно :) – TrystanC

9

еще более простой подход:

ko.observable.fn.silentUpdate = function(value) { 
    this.notifySubscribers = function() {}; 
    this(value); 
    this.notifySubscribers = function() { 
     ko.subscribable.fn.notifySubscribers.apply(this, arguments); 
    }; 
}; 

Используйте его как follo ws:

this.status = ko.observable("Happily Married"); 
this.walkIntoBar(); 
this.status.silentUpdate("Single"); 
this.walkOutOfBar(); // careful with exceptions 
this.status.silentUpdate("Happily Married"); 

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

1

Я пришел к этому вопросу, потому что я строил выгружаемый datagrid. Было показано только 10 строк, и каждая строка имеет флажок. В заголовке таблицы был флажок (de) select all.

Во время нагрузочных испытаний мы обнаружили, что при щелчке по флажку «Выбрать все» удалось обновить 1000 наблюдаемых одновременно. Это заняло слишком много времени.

Казалось, что KO обновил html 1000 раз, хотя только 10 наблюдаемых были привязаны к HTML.

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

http://knockoutjs.com/documentation/deferred-updates.html

Смежные вопросы