My application has a View() model that fetches HTML, CSS, etc. with a simple call to a view path. As many of these views and viewlets are shared or required multiple times I'd like to maintain a 'cache' object of loaded views that any new instance of a View() can check and read from if that particular view has been loaded.
In a requireJS implementation, any ideas on where is best to put this view 'cache' object? Ideally I'd like to have something like a Session() object that contains it, and I'd be able to reference a single instance of Session() from anywhere in my app.
Any thoughts on best practices for this?
Many thanks!
I suggest you to use a Singleton approach creating a simple module for this case. For instance, you could create a module like this:
define(["mydep","myotherdep"], function(dep1,dep2){
var Hellovariable = {
"attr1": ...,
"attr2": ...,
...
"attrN": ...
}
return Hellovariable;
});
When you call this module using AMD you will only have an unique instance for this variable and its attributes.
Related
I have a variable (a constructed filename) that I need to get from within an API in one file to be stored as a variable in another file.
The way my code is set up, there's not really a way (that I can think of) to get this variable from one file to another without using globals. I've been looking around at a few different methods and decided to create a globals module (globals.js):
var globals = {
'new_img': ''
}
module.exports = globals;
I've written:
var globals = require('./public/js/globals');
In my server.js and in my routes.js so that all of my API's and controllers have access to this module.
When I serve this web application and multiple people have their own instances of the webpage, will they all be using the same globals module? This is not my desired effect. What would be better ways of going about this?
yes they will be using the same instance.
That pattern is a singleton, you're exporting and making global a variable, the same spot in memory will be visibile by the whole app.
With the help of the debugger you can analyze the require code in depth and see that Nodejs will cache the result of that call and return the same instance everytime.
NodeJS source code:
if your desired result is to have different instances you can shallow clone the object.
var globals = _.extend({}, require('./public/js/globals')); //ecma5 + underscore.js
var globals = Object.assign({}, require('./public/js/globals')); //ecma6
Is there a convenient approach to code organization, which allows to create a module pattern, but define its internally exposed functionality in separate files.
So, with a module below, can SomeInternalObject2 be defined in another js file and still be accessible from the first file (assuming proper ordering of script files)?
var MyModule = (function(){
function SomeInternalObject1(){..}
function SomeInternalObject2(){..}
return {
this.publicFunction = function(){..}
}
})();
EDIT: Perhaps I'm thinking about it in a wrong way. Code organization is a development-time concern. Require.js, module-loading, etc.. is a run-time concern.
Have look at jTable (javascript). The author augments the main object from different files. It is not exactly what you are asking for, but the intention or goal seems similar. I might add code later.
I am mildly familiar with require.js and Backbone.js having used them together for about a year now and relatively new to Backbone.Marionette although I am very interested in what it can bring to the table.
In looking for examples of project structure (I can get a little obsessed with this stuff) I have found https://github.com/BoilerplateMVC/Marionette-Require-Boilerplate and other similar examples.
Something that has been bothering me: in their app.js file, they return a reference to an instance of a Marionette application, ie:
var app = new Backbone.Marionette.Application();
app.addInitializer(...);
...
return app;
And in many components, they reference the app.js via require.js and use as follows:
define([..., 'app'], function (... , App) {
App.someProperty(...);
});
Now here's what I'm not understanding: I have been under the assumption that the code in their app.js is really more like a Factory than a Class since it returns an instance of an application rather than, say, a modified prototype or extension thereof.
Therefore, when they reference app.js, aren't they actually creating a whole new instance rather than accessing some sort of shared instance? There is nothing to suggest that app.js is returning a singleton in their code.
And yet, it works, and obviously I am the one who is confused.
So, why does this work?
This works because objects are passed by reference in javascript and the fact that require.js only loads every dependency once. Then, app.js returns an initialized instance, and every other module that requires 'app' gets reference to the same object.
It's not a factory, it's simply an initialized application object instance.
I have a few different angular modules that will share the same method. These modules don't really lend themselves to inheritance, but I want to remain DRY. Thus I wanted to use the mix-in pattern. In the project I'm working on, we are also using underscore js. I'm trying to instantiate an angular module for my mixin as follows:
angular.module('my.module', [])
.factory('myMixinFunction', function () {
_.mixin({
myMixinFunction: function (param) {
// do something
return;
}
});
});
Now my question is, how do I load this mixin into another module? I'm thinking it would look something like this -
angular.module('some.other.module', ['my.module'])
.factory('myOtherModule', function (myMixinFunction) {
/// Other module code
});
I know I'll have to list the mixin module as a dependency, but where do I actually perform the extension? Ideally, I would like my mixin to be able to access the elements within 'myOtherModule'. Anyone have any advice on this? Is there an 'angular way' to accomplish this?
Instead of using underscore's _.mixin() functionality, you might want to instead define myMixinFunction as a service. See: What is the difference between module.factory and module.service and how might both be applied?, noting services/usage: "Usage: Could be useful for sharing utility functions"
In one of the rails app I am trying to use backbone with "rails-backbone" gem,
And I have created one model using scaffolding which is working fine.
but I have another model and I am trying to use different router for it, but when tries to instantiate that router from index.html.erb it fires,
"Uncaught TypeError: undefined is not a function" which clearly means there is no such router. But it is there and even in developer's tool it shows those JS files. I tried all different ways but it didn't work. Thanks in advance.
I'd guess that you're defining your router like this:
class SomeRouter extends Backbone.Router
# router code goes here
and then you're trying to create one with:
r = new SomeRouter
But CoffeeScript will wrap your files in a function to prevent scope creep:
Although suppressed within this documentation for clarity, all CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult to pollute the global namespace by accident.
If you'd like to create top-level variables for other scripts to use, attach them as properties on window, or on the exports object in CommonJS. The existential operator (covered below), gives you a reliable way to figure out where to add them; if you're targeting both CommonJS and the browser: exports ? this
That wrapper will hide SomeRouter inside a function so there will be no SomeRouter visible outside the file which defines it.
A common solution in Rails/Backbone apps is to manage the namespaces yourself. Set up your own namespace somewhere before any other (Java|Coffee)Script will be pulled in:
# AppName is just a placeholder, you'd use something more
# sensible in real life.
window.AppName =
Routers: { }
Views: { }
Models: { }
Collections: { }
and then define your router as:
class AppName.Routers.SomeRouter extends Backbone.Router
#...
and later:
r = new AppName.Routers.SomeRouter
similarly with models, collections, and views that need to be globally visible.