2

I've frequently had need to have my own library emit events via callback subscriptions and in some cases I prefer to just use Javascript function variables directly rather than some third party library or the DOM to manage events. I've found two strategies and I'm not sure which one is more appropriate.

These strategies are demonstrated with this JSFiddle: http://jsfiddle.net/Q8pQT/2/

The first strategy is to add each subscription to a function array, so when I am ready to invoke an event I can iterate through all callbacks in the event.

var fnactionidx = 0;
var fnarr = [];
function add2fnArray() {
    fnarr.push(fnaction);
    console.log("added to array", fnarr.length);
}
function fnaction() {
    console.log("Hi.", ++fnactionidx);
}
function arraygo() {

    // do internal stuff here first

    fnactionidx = 0;
    for (var i=0; i<fnarr.length; i++) {
        fnarr[i]();
    }
    console.log("array complete!")

    // do internal stuff here last
}

Subscribing in this example is done with a simple Array.push(fn).

The second strategy is to define an initial function, then for each subscriber, wrap it with a containing function.

function fnactionnested() {
   console.log("nested complete!");

    // do internal stuff here last
}

function nestfn(fn) {
    var na = fnactionnested;
    fnactionnested = function() {
        fn();
        na();        
    }
    console.log("nested " + fn.toString());
}
function nestgo() {
    // do internal stuff here first
    fnactionidx = 0;
    fnactionnested();
}

Subscribing in this example is done with nestfn. Note that I don't really care which sequential order the execution occurs in since it's explicit; in the first example I could've used Array.unshift.

I've seen the 2nd one recommended more. My suspicion is that, while the 2nd one is more Javascript-like in that it takes advantage of Javascript being flexible with functions as a functional language, it probably introduces significantly more memory overhead since you have functions inside of wrapper functions inside of wrapper functions, and so on, depending on how many subscribers there are.

Any thoughts on which approach is preferable?

Note that I do not want to use a string-based event subsystem, I only want to distinguish between these two strategies, or if there is another callback strategy that does something very similar to these two without going through some "global" event system with some string key.

4

1 回答 1

0

Knockout 可订阅的订阅实现(第 35 行)来看,使用数组进行事件订阅似乎是相当流行的先例。

对于基于数组的支持取消订阅此类事件,还有一个重要的论据。使用数组可以做到这一点;使用函数包装几乎是不可能的。

另外,函数包装,当你把头绕在它周围时,很奇怪,它可能更容易编写,但并不容易支持。另一方面,有时您别无选择,例如当另一个模块已经实现了一个事件并且您的目标是在应用程序代码中的其他回调对其执行之前执行一些预处理。

于 2013-09-09T00:48:49.490 回答