2
\$\begingroup\$

Previous question:

JavascriptObservable Storage

The idea is to have some storage interface that exists of different buckets - known as Eagles:

Eagle('bucket1');
Eagle('bucket2');

Every Eagle data is stored as Feathers.

var e = Eagle('fooEagle');
e.set('myFeather',{
    'foo' : 'bar';
});

These Feathers can be observed for changes (nothing more at this moment):

var f = e.get('myFeather');
f.on('change',function(f, key) {
    console.log(key+ ' index of the Feather was changed to'+ f.get(key)));
});
f.set('foo','newer foo');

You could also retrieve data in a long chain like this:

Eagle('fooEagle').get('myFeather').get('foo');

Does this seem like a good approach? If so, how would you implement events like 'delete'. And would it be useful to let those events bubble up to the Eagle? If so, how?

window.Eagle = (function(){
    "use strict";

    var _eagleInstances = [],
        _featherInstances = [];

    var Feather = (function() {
        var _data = {},
            _observers = {};

        var F = function(data) {
            this._id = _featherInstances.length;
            _featherInstances[this._id] = this;
            _data[this._id] = data;
        }

        F.prototype.has = function(key) {
            return _data[this._id].hasOwnProperty(key);
        }

        F.prototype.get = function(key) {
            return this.has(key) ? _data[this._id][key] : undefined;
        }

        F.prototype.set = function(key, data) {
            _data[this._id][key] = data;
            this.notify('change', key);
            return this;
        }

        F.prototype.on = function(action, callable) {
            if ( ! _observers.hasOwnProperty(action) ) {
                _observers[action] = [];
            }

            _observers[action].push(callable);
        }

        F.prototype.notify = function(action, info) {
            if ( _observers.hasOwnProperty(action) ) {
                for ( var i = 0; i < _observers[action].length; i++ ) {
                    _observers[action][i](this, info);
                }
            }
        }

        return F;
    })();

    var Eagle = (function(){
        var _feathers = {};

        var E = function() {
            this._id = _eagleInstances.length;
            _feathers[this._id] = {};
            _eagleInstances[this._id] = this;
        }

        E.prototype.has = function(featherIdentifier) {
            return _feathers[this._id].hasOwnProperty(featherIdentifier);
        }

        E.prototype.get = function(featherIdentifier) {
            if ( !this.has(featherIdentifier) ) {
                this.set(featherIdentifier, {});
            }
            return _featherInstances[_feathers[this._id][featherIdentifier]];
        }

        E.prototype.set = function(featherIdentifier, data) {
            var f = new Feather(data);
            _feathers[this._id][featherIdentifier] = f._id;
            return f;
        }

        return E;
    })();

    return function(eagleIdentifier) {
        if ( !_eagleInstances.hasOwnProperty(eagleIdentifier) ) {
            _eagleInstances[eagleIdentifier] = new Eagle();
        }
        return _eagleInstances[eagleIdentifier];
    }

})();
\$\endgroup\$
  • \$\begingroup\$ A good primer on how Collections (Eagles) and Models (Feathers) work would be Backbone. Check it out and model your stuff around it. \$\endgroup\$ – Joseph Oct 7 '14 at 15:19
1
\$\begingroup\$

I am just going to comment on a few things because I don't think I have a great high level understanding of your code is meant to do (not that is bad for any reason).

In general I would avoid adding scope to variables if it is not needed, for example instead of declaring _data that is available to the whole F class and reference it with a special id I would just put a new data object on each instance. Keep in mind limiting the scope of variables would apply for _featherInstances and _eagleInstances as well but there could be some business reason for it that I don't understand.

     var F = function(data) {
                this._id = _featherInstances.length;
                _featherInstances[this._id] = this;
                this._data = data;
            }

        F.prototype.has = function(key) {
            return this._data.hasOwnProperty(key);
        }
   ...

Another note to make is has might not work as you expected it. For example:

new F({key: undefined}).has('key') would return true

\$\endgroup\$
  • \$\begingroup\$ The reason I scope the _data var is to make it unaccessible from the outside. otherwise one could access the data using F._data \$\endgroup\$ – Pinoniq Oct 8 '14 at 12:21
  • \$\begingroup\$ I wouldn't worry about that, _data indicates that it is private and no matter what it is named if it is not documented it is not part of your public api. I generally avoid code overhead and closures to prevent someone from possibly doing something wrong. \$\endgroup\$ – pllee Oct 8 '14 at 14:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.