On Thu, Nov 6, 2008 at 12:27 AM, Giulio Cesare Solaroli <[EMAIL PROTECTED]> wrote: > It has happened to me to require registering an observer before the > actual source of the signal was created. In these cases, I would just > register the observer to listen to a given signal on any source. Later > the relevant object would signal the right message and the observer > would be triggered.
Ok, but then you also have to filter away the same signal when originated in other objects, right? > Or, I need to update an object, whatever it happens to it. So I can > register for any signal on that given object and trigger an action. This is kind of interesting. When using MochiKit.Signal, you would depend on the user calling signal() for each change performed, which might be unpractical in some cases. Also, when scaling this up for many objects, you'll run into linear performace degradation due to the looping through of the MochiKit.Signal._observers array. An alternative implementation to signals (compared to MochiKit), would be based on the signal-slot concept from Qt (and elsewhere). In that model all non-DOM signals are functions, as are all slots. And the connect() function simply attaches some pre-call and post-call logic to each signal function, making sure that the connected slot functions are called. Using that model, source objects are modified. But since there are no lists, there is no performance penalty to using many non-DOM signals. Also, the need for the signal() function would be none, since the following would do the job: // setting up objects var src = { srcMethod: function() { alert("source"); } }; var dst = { dstMethod: function() { alert("dest"); } }; // connecting a signal with the signal-slot mechanism Signal.connect(src, "srcMethod", dst, "dstMethod"); // calling both the signal function and the slot function src.srcMethod(); Using this model, it would be trivial to create proxy-objects. I.e. objects that are copies of a source object, but also calls some handler code before and after each function call. Don't know if that would be so very useful, though. But a nice hack. :-) If anyone is interested, here is some old code I had in my own signal module before migrating to MochiKit.Signal (stripped for comments & logging to save space): Signal = {}; Signal.connect = function(src, signal, destOrFunc, funcOrStr) { if (typeof(signal) != "string") { throw new TypeError("signal name must be a string"); } var slot = Signal._createSlot(destOrFunc, funcOrStr); this._connectDispatcher(src, signal); src[signal].postFuncs.push(slot); } Signal.connectBefore = function(src, signal, destOrFunc, funcOrStr) { if (typeof(signal) != "string") { throw new TypeError("signal name must be a string"); } var slot = Signal._createSlot(destOrFunc, funcOrStr); this._connectDispatcher(src, signal); src[signal].preFuncs.push(slot); } Signal.disconnectAll = function(src, signal) { if (src == null) { throw new TypeError("signal object cannot be null"); } if (signal != null) { if (typeof(signal) != "string") { throw new TypeError("signal name must be a string"); } this._disconnectDispatcher(src, signal); } else { for (var n in src) { if (typeof(src[n]) == "function") { this._disconnectDispatcher(src, n); } } } } Signal._createSlot = function(destOrFunc, funcOrStr) { if (typeof(funcOrStr) == "string") { if (typeof(destOrFunc[funcOrStr]) != "function") { throw new TypeError("signal slot '" + funcOrStr + "' is not a function"); } return MochiKit.Base.bindLate(funcOrStr, destOrFunc); } else if (typeof(funcOrStr) == "function") { return MochiKit.Base.bindLate(funcOrStr, destOrFunc); } else if (typeof(destOrFunc) == "function") { return destOrFunc; } else { throw new TypeError("signal slot is not a function"); } } Signal._connectDispatcher = function(src, signal) { if (src == null) { throw new TypeError("signal object cannot be null"); } else if (!(signal in src)) { throw new TypeError("signal '" + signal + "' doesn't exist in object"); } var value = src[signal]; if (value != null && typeof(value.signalFunc) == "function") { return; } src[signal] = function() { var self = arguments.callee; var res; Signal._callSlots(self.dispatchName, self.preFuncs, this, arguments); if (typeof(self.signalFunc) == "function") { res = self.signalFunc.apply(this, arguments); } Signal._callSlots(self.dispatchName, self.postFuncs, this, arguments); return res; } src[signal].signalFunc = value; src[signal].preFuncs = []; src[signal].postFuncs = []; } Signal._disconnectDispatcher = function(src, signal) { if (src == null) { throw new TypeError("signal object cannot be null"); } else if (!(signal in src)) { throw new TypeError("signal '" + signal + "' doesn't exist in object"); } var value = src[signal]; if (value == null || typeof(value.signalFunc) != "function") { return; } src[signal] = value.signalFunc; value.signalFunc = null; value.preFuncs = null; value.postFuncs = null; } Signal._callSlots = function(signalName, slots, obj, args) { for (var i = 0; i < slots.length; i++) { try { slots[i].apply(obj, args); } catch (e) { MochiKit.Logging.logError("Uncaught exception in call from " + signalName, e); } } } > How do you see integration between signals and deferred? > > I am very interested in this, as our application make extensive use of > both, and we are now thinking about removing our custom notification > center in order to simplify all signaling code and settle for a single > API, and we are going to consolidate on MochiKit.Signal. Basically I'm thinking along the lines of MochiKit.AJAX. But I'd like to be able to keep different AJAX calls separated. So perhaps like this (with improved naming of course): // create a generic HTTP/Ajax dispatcher object var dispatcher = new HttpDispatcher({ url: "http://localhost/json/", method: "POST", response: "JSON" }); // create some functions that performs AJAX calls dispatcher.createFunction("getUsers", { method: "GET" }); dispatcher.createFunction("updateUser", { args: ["name", "email"] }); // call the functions and get a deferred objects back dispatcher.getUsers(); dispatcher.updateUser('john', '[EMAIL PROTECTED]'); // connect signals to specific methods (signals on AJAX response) connect(dispatcher, "getUsers", doSomething); // connect signals to generic AJAX events on the dispatcher connect(dispatcher, "onresponse", doSomethingElse); connect(dispatcher, "onerror", alert); Anyway, the above is just an idea that I'm playing around with. Haven't thought so much about this, actually... :-) Cheers, /Per --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "MochiKit" group. To post to this group, send email to mochikit@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/mochikit?hl=en -~----------~----~----~----~------~----~------~--~---