Question

Is it possible to overload a pre-existing subscription on an observable and if so how?

this.myObservable = ko.observable();
this.myObservable.subscribe(function(value){
    /* stuff worth subscribing for */
});
/* stuff going on */
/* ... */
/* more stuff going on */

// now at this point I want to check if something has subscribed to
// this.myObservable and if so I want the subscription to do a bit extra

I understand that I could place the "bit extra" in the initial subscription in the first place, but I want to know if it's possible to check for the subscription and then overload it.

Was it helpful?

Solution 2

Knockout doesn't provide any way to extend a subscription. But you could wrap the subscribe method to provide a way to do so. Here's an example:

ko.subscribable.fn.subscribe = (function (originalFunction) {
    return function (callback, callbackTarget, event) {
        var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback,
            currentCallback = boundCallback,
            passthroughCallback = function (value) { currentCallback(value) },
            subscription = originalFunction.call(this, passthroughCallback, null, event);

        subscription.extend = function (newCallback) {
            currentCallback = newCallback.bind(null, currentCallback);
        };
        return subscription;
    }
})(ko.subscribable.fn.subscribe);

http://jsfiddle.net/mbest/LKrr9/

You also mention being able to retrieve a subscription from an observable later on. You might accomplish that by adding a line in the function above like this:

this.latestSubscription = subscription;

This assumes that subscriptions won't be disposed. If you want to get the latest non-disposed subscription, it'll be a bit more complicated.

NOTE: The above method of extending subscribe only works in Knockout >=3.1.0. For prior versions, you've have to attach the new subscribe method in an extender.

OTHER TIPS

I am sure there is a magical JavaScript way of doing it but one way that just came to mind for some reason when reading this (not that fancy, mind you) is like this -

function doSomething() { alert('Hey'); }
function doSomethingElse() { alert('Hey2'); }

ko.extenders.functionAdder = function (target, firstFunc) {
    target.functionBag = target.functionBag ? target.functionBag : [];
    target.functionBag.push(firstFunc);
    target.subscribe(function(value){
        ko.utils.arrayForEach(target.functionBag, function (item) {
            item();
        }); 
    });
}    
self.things = ko.observableArray([new Message('Hey')]).extend({ functionAdder: doSomething });

// Later on

target.functionBag.push(doSomethingElse);

Example -

http://jsfiddle.net/k94qT/

There may be a more appropriate way to reopen the function and add things to it but that sounds like Ember.js's reopenClass and I don't know of anything like that in Knockout.js

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top