web-dev-qa-db-fra.com

Changement observable mais ne prévenez pas les abonnés dans knockout.js

Existe-t-il un moyen d'ignorer les abonnés lors d'un changement de valeur de l'observable. Je voudrais changer la valeur d'un observable, mais pas l'exécuter pour les abonnés avec knockout.js

43
Mike Flynn

Normalement, cela n'est ni possible ni conseillé, car cela permet potentiellement aux choses de se désynchroniser dans les chaînes de dépendance. L'utilisation de l'extenseur d'accélérateur est généralement un bon moyen de limiter la quantité de notifications reçues par les dépendances.

Cependant, si vous voulez vraiment faire cela, alors une option serait d'écraser la fonction notifySubscribers sur un observable et de lui faire vérifier un drapeau.

Voici une extension qui ajoute cette fonctionnalité à un observable:

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;
};

Vous ajouteriez ceci à un observable comme:

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

Ensuite, vous le mettriez à jour sans notifications en faisant:

this.name.sneakyUpdate("Ted");
82
RP Niemeyer

Une approche encore plus simple:

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

Utilisez-le comme suit:

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

À utiliser avec prudence. Nous avons affaire à un objet observable afin que de mauvaises choses puissent se produire si vous ne notifiez pas vos abonnés.

14
Steven de Salas

J'aime la solution fournie par @ RP Niemeyer lorsque tous les abonnés doivent être ignorés. Cependant, pour mon cas, j'ai un observable avec des liaisons bidirectionnelles sur un contrôle Select. Lorsque vous utilisez @ RP Niemeyer, le contrôle Select n'est pas mis à jour. Donc, j'avais vraiment besoin d'un moyen de désactiver certains observateurs, pas tous. Voici une solution généralisée pour ce cas.

Ajoutez des méthodes d'extensions pour les abonnements "silencieux" et les écritures "silencieuses".

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;
};

Vous souscririez à observable comme:

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

Ensuite, vous le mettriez à jour sans notifications spécifiques en procédant comme suit:

this.name.poke("Ted");   // standard subscribers still get notified
7
raider33

Je suis venu à cette question parce que je construisais une grille de données paginée. Seules 10 lignes ont été affichées et chaque ligne a une case à cocher. L'en-tête du tableau comportait une case à cocher (dé) sélectionner tout.

Lors des tests de charge, nous avons découvert que le fait de cliquer sur la case à cocher Sélectionner tout entraînait la mise à jour de 1000 observables à la fois. Cela a pris beaucoup trop de temps.

Il semblait que KO a mis à jour le html 1000 fois même si seulement 10 observables étaient liés au HTML.

Si quelqu'un trouve cette question pour la même raison, je suggère de rechercher des mises à jour différées. File d'attente de mises à jour différées notifiant les abonnés, elle avertit vos abonnés une fois votre "thread" terminé. Les mises à jour différées sont configurables par observable ou pour l'ensemble de votre application.

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

1
Rob