The best way to share the same functionality in Ba

2019-09-06 15:54发布

I am in the current situation: for a Backbone.Collection (but it should be also for a Backbone.Model), I extend the class in this way(1).
The functionality I want to share are the following:
1) startPolling and stopPolling should be public method accessible from all Backbone.Collections and eventually Backbone.Models
2) executePolling and onFetch should be private method.

What is the best way to share startPolling and stopPolling between all Backbone.Collection/Backbone.Model keeping executePolling and onFetch private method?

My idea is to create a new file utils/backbone.polling.js(2). Is it good solution?


(1)

define([
    'backbone',
    'models/myModel'
], function (Backbone, MyModel) {
    'use strict';

    var MyCollection = Backbone.Collection.extend({

        model: MyModel,

        url: 'some_url'

        initialize : function () {
            _.bindAll(this);
        },

        startPolling: function () {
            this.polling = true;
            this.minutes = 2;
            this.executePolling();
        },

        stopPolling: function () {
            this.polling = false;
        },

        executePolling: function () { 
            this.fetch({success : this.onFetch});
        },

        onFetch: function () {
            if (this.polling) {
                setTimeout(this.executePolling, 1000 * 60 * this.minutes);
            }
        }
    });

});

(2)

utils/backbone.polling.js

Backbone.Collections.startPolling = function () {
    // code here
};

Backbone.Collections.stopPolling = function () {
    // code here
};

3条回答
做个烂人
2楼-- · 2019-09-06 16:22

Despite the very elegant approaches of @Flops and @jakee a very simple one could be having a pure JS utils library like:

// code simplified and no tested
App = {};
App.Utils = {};
App.Utils.startPolling: function () {
  this.polling = true;
  this.minutes = 2;
  this.executePolling();
},

var MyCollection = Backbone.Collection.extend({
  startPolling: App.Utils.startPolling;
});
查看更多
不美不萌又怎样
3楼-- · 2019-09-06 16:43

For private methods, in my best knowledge I have no recollection of javascript offering a way to make an attribute within an object 'private'. The only way I can think of is to make the 'private' methods available only from within the methods they are used in.

startPolling: function () {
  this.polling = true;
  this.minutes = 2;

  var self = this;
  var executePolling = function() {
    // Do something
  };

  var onFetch = function() {
    // Do something
  }; 

  executePolling();
},

But this way you don't get dynamic access to the objects attributes from the functions within functions (they just save the values from the state of affairs when they are created) (Link to fiddle exhibiting this phenomena). If you want access to the objects attributes values that are up-to-date, then you have to make the functions public. I think that a good convention would be just to name the 'private' functions with a leading underscore to signify them being private (like this _executePolling and _onFetch).

As for the best way to share. A good-looking solution could be something like this:

 var WestCoastCustoms= {
   // Declare your stuff here
 };

 var Collection = Backbone.Collection.extend(WestCoastCustoms);
 var Model = Backbone.Model.extend(WestCoastCustoms);

A working fiddle example here

Hopefully this helped!

查看更多
Luminary・发光体
4楼-- · 2019-09-06 16:47

You can extend Collection prototype to add public methods to every collection you have (if you reallly need it every where). In other case you can create your own constructor with this methods (first way).

_.extend(Backbone.Collection.prototype, {
    startPolling: function() {},
    stopPolling: function() {}
});

For the case of the provate methods you can do the same just start they are names with underscore:

_.extend(Backbone.Collection.prototype, {
    _executePolling: function() {},
    _onFetch: function() {}
});    

This way of naming methods shows that this is a private method.

If you want them in Model you can extend the Model prototype or create a new constructor function of your model like in examples upper. If this functions are the same (hope not), you can give a link to a function, not a function it self.

var bar = function() {};

_.extend(Backbone.Model.prototype, {
   foo: bar
});

_.extend(Backbone.Collection.prototype, {
   foo: bar
});

So when you will change bar function it will be changed in Model and in Collection.

查看更多
登录 后发表回答