Accessing variable from different files(module) using requirejs - javascript

I am trying to make MVC structure of application in canjs. For that I am using requireJS to separate the code in different file.
I have searched in google and i am following this tutorial but in that tutorail I dont find to access module variables in different modules. therefore I am following this method to do so.
But I cannot achieve that.
This is my code:
requirejsconfig.js file :
requirejs.config({
paths :{
enforceDefine: true,
waitSeconds : 0,
jquery : "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min",
main : "view/main",
player : "view/player",
PlayerModel : "/models/PlayerModel",
hbs : "/models/view/js/handlebars",
fixture : "/models/view/js/can.fixture",
can : "/models/view/js/can.jquery"
}
});
main.js :
require(["player"],function(player){
player.PlayerModel();
});
I want to use that model methods in my controller.
player.js :
define(['PlayerModel'],function(){
function PlayerModel(){
var Player = PlayerModel.Player;
Players =can.Control({ defaults :{view:view/players.hbs' }},{
init: function(){
this.element.html(can.view(this.options.view, {
players: this.options.players
}));
}
$(document).ready(function(){
$.when(Player.findAll()).then(
function(playersResponse){
var players = playersResponse[0];
new Players('.players', {
players: players
});
});
});
}
});
PlayerModel.js:
define(function(){
var Player = can.Model({
findAll: 'GET /models/players.json',
findOne: 'GET /players.json/{id}'
});
return {
Player:Player
}
});
Every file is being loaded (saw in network tab-chrome devtools) but nothing is being populated in output.
Can anybody help me ?
Thanks in advance!

Carrying on with what #ekuusela said, restructure the code in Player.js in this format:
define(['PlayerModel'],function(){
function PlayerModel(){ ... }
return {
PlayerModel: PlayerModel
}
});
What's happening
Internally, two conventions are followed when defining modules. These relate to:
What the module is called (its label)
What this label represents.
Labeling Modules
The filename is taken as the module's name (unless shim is used, like you have). In other words, the define(['Module_Name'] ...), which is how I would normally read that line, can more accurately be read as a define(['Module_Path_Or_Shim_Symbol_Name' ...)
What Is This 'Module' Anyway
A module isn't magic - it is just a specially labeled map to a function. This map is maintained by RequireJS and probably looks similar to this:
var ModuleMap = {
'Player' : function (...) { ... },
'PlayerModel' : function (...) { ... }
};
Every time a module is accessed, through a require or define call, this map is accessed, and the relevant function found. However, that isn't enough - what we want is the stuff that is defined within the function - the fundamental concept of modules is that everything inside them has Module Function Scope, and is not exposed outside. So, to gain access to this "stuff", the RequireJS brain does the only thing it can do with a function - execute it.
var playerReference = require('Player');
Note that I've used the CommonJS notation of requiring modules, which is more readable for our current purpose.
So, in the code you posted, the module function has defined and declared PlayerModel as a function, but has not exposed it. Since the line player.PlayerModel() expects the module to return an object with a property named PlayerModel that refers to your function, the logical return value of the module is:
var exposedModuleReference = { PlayerModel: PlayerModel };
return exposedModuleReference;
Note that this means the name with which the function is exposed can be different from the function name itself. For example, the following code will also work without any changes anywhere else:
define(['PlayerModel'],function(){
function PlayerModelConstructor(){ ... }
return {
PlayerModel: PlayerModelConstructor
}
});
An Interesting Addition
So, executing a module function and assigning that return value to a reference is one part of what RequireJS's brain does. The other part is, it then updates this map so it now looks like this:
var ModuleMap = {
'Player' : { PlayerModel: PlayerModelConstructor },
'PlayerModel' : function (...) { ... }
};
This means that code written in module functions gets executed at most one time.

You define the function PlayerModel inside player.js and then require a module called PlayerModel there but don't assign the required module to any variable. You should first clean up your code, possibly rename some of your modules and move functions around.
Here, you try to access the function PlayerModel in the module player, but the module factory function in player.js doesn't return anything:
require(["player"],function(player){
player.PlayerModel();
});
What gets assigned to the function parameter player is only whatever you return from the function that defines the module. (If you would define a module as an object then that object would be the argument.)

Related

use `module` as namespace

I've been using a pattern in my node.js modules that seems so obvious to me that I assume there must be something wrong with it or I would see more people doing it. To keep private variables that are global to the module, I simply attach them as properties on the module object. Like so:
module.exports = {
init: function() {
module.someClient = initializeSomethingHere()
},
someMethod: function(done) {
module.someClient.doSomething(done)
}
}
This seems preferable to me than something like this...
var someClient;
module.exports = {
init: function() {
someClient = initializeSomethingHere()
},
someMethod: function(done) {
someClient.doSomething(done)
}
}
...because in the second example you need to go searching for var someClient at the top of the file to make sure that the omission of the var keyword is intentional within the init method. I've never seen this pattern used elsewhere though, so I wonder if I'm missing something that makes it less than ideal.
Thoughts?
There are a couple of possible downsides that come to mind.
1) It's technically possible for those properties to be accessed and modified outside the module, but only if a reference to the module itself is available outside it. Something that makes the module available through its own exports (module.exports = module; being the simplest example) would expose them.
2) You could have a naming conflict with a builtin property or a future builtin property that doesn't exist yet (which would cause your code to break in future versions of node.js). This could be very problematic and very hard to debug. Currently the built-in properties on a module object are: children, exports, filename, id, loaded, paths, and parent.
because in the second example you need to go searching for var someClient at the top of the file to make sure that the omission of the var keyword is intentional within the init method.
If that is the reason, you could just use a namespace that isn't module. For instance by adding var private = {}; to the top of each file and then using private.someClient instead of module.someClient.
Also 'use strict'; so that the accidental omission of var is an error and not an accidental global.
Drawbacks
Option 1: This practice is prone to naming conflict with a builtin property or a future builtin property that doesn't exist yet, as #paulpro stated in his answer.
Option 2: If you miss var keyword and expose the someClient globally. Besides you need to go searching for var someClient at the top of the file all the time.
Alternative
As JavaScript has function scope it's better to define everything within a function. Creating private and public members within a function. Below is a design pattern which one can follow:
'use strict';
module.exports = (function(){
//private
var someClient;
//public properties
var that={};
that.init = function() {
someClient = initializeSomethingHere()
},
that.someMethod: function(done) {
someClient.doSomething(done)
}
//expose only the required methods
return that;
})();
Here only exposed methods are those which are attached to that object. And all rest are private to the function scope. Even if you miss the var keyword in someClient it won't be accessible out side of the function, which won't ever happen if you use 'use strict' at the top.
Logic is first time when you require the xyz.js file it will return the that object rather than the function.

js - avoiding namespace conflict

Thus far I've worked only with relatively small projects (and mostly alone), but this time I have to collaborate with other programmers... basically because of that I must plan the structure of the website very carefully for the avoidance of spending hours debugging the code.
At this point I suppose doing that in the following manner. I divide my code in modules and store each module in a separate file inside an object (or a function) with a made-up name (lzheA, lzheB, lzheC etc.) to avoid conflicts whether an object with the same name was used in an another piece of code. When the document is loaded, I declare a variable (an object) that I use as a main namespace of the application. Properties of the object are the modules I defined before.
// file BI.lib.js
var lzheA = {
foo: function() {
},
bar: function() {
},
}
// file BI.init.js
function lzheK() {
BI.loadPage();
}
// file BI.loadPage.js
function lzheC() {
var result = document.getElementById('result');
result.innerHTML = "that worked";
}
// and so on
var lzheA,lzheB,lzheD,lzheE,lzheF,lzheG,lzheH,lzheI,lzheJ;
// doing the following when the document is loaded
var BI = {
lib: lzheA,
menu: lzheB,
loadPage: lzheC,
customScripts: lzheD,
_index: lzheE,
_briefs: lzheF,
_shop: lzheG,
_cases: lzheH,
_blog: lzheI,
_contacts: lzheJ,
init: lzheK,
}
BI.init();
https://jsfiddle.net/vwc2og57/2/
The question... is this way of structuring worth living or did I miss something because of lack of experience? Would the made-up names of the modules confuse you regardless of the fact that each one used only twice - while declaring the variable and assigning it to a property?
I consider the namespaces a good option when you want to modularize applications in Javascript. But I declare them in a different way
var myModule = myModule || {}; // This will allow to use the module in other places, declaring more than one specificComponent in other js file for example
myModule.specificComponent = (function(){
// Private things
var myVar = {};
var init = function() {
// Code
};
return {
init: init // Public Stuff
};
})();
If you want to call the init method, you would call it like this
myModule.specificComponent.init();
With this approach, i guarantee that the module will not be overwritten by another declaration in another place, and also I can declare internal components into my namespaces.
Also, the trick of just exposing what you want inside the return block, will make your component safer and you will be encapsulating your code in a pretty way.
Hope it helps

Does Dojo AMD loader ensure modules are executed only once?

In some existing Dojo-based app I am seeing a module using a singleton pattern of the form:
define([...], function(...) {
var MyClass = declare(...);
if (!_instance) {
var _instance = new MyClass();
}
return _instance;
});
But if I understand AMD correctly, the usage of _instance is not required, because the function passed to the define(...) call should be executed only once... or maybe not?
My understanding of the AMD loader is that when getting a module by calling "require" or "define", it will check whether the module has already been loaded. If it has not been loaded yet, it will load the JS, execute the function passed to "define", and internally store the returned value. If it has already been loaded, it will simply return the previously-stored value.
Are my assumptions correct? If so, when writing a module, we can safely assume that a given module will only be loaded and executed once, and we don't need to perform any check to see whether something has already been initialized or not, making the code simpler.
Thank you.
You are right i a way, but not entirely
define("my.widget", [ "dojo/_base/declare",.... ], function(declare, ...){
return declare("my.widget", [ .. ], {
value : "myvalue"
});
});
here we define module which defines class, so class declaration(constructor) is cached when module is required, meaning class is defined only once. But that doesn't mean you can use it as static, because that's only class declaration, not the instance.
this will not work:
require(["my.widget"], function(widget) {
console.log(widget.value);
});
Here is correct usage:
require(["my.widget"], function(widget) {
console.log(new widget().value);
});

backbone.js Issue with module defining

I follow this pattern to organize my js application.
As that example says our application should has the single entry point. File application.js doing that work.
// Filename: application.js
var chat = {
// Create this closure to contain the cached modules
module: function() {
// Internal module cache.
var modules = {};
// Create a new module reference scaffold or load an
// existing module.
return function(name) {
// If this module has already been created, return it.
if (modules[name]) {
return modules[name];
}
// Create a module and save it under this name
return modules[name] = { Views: {} };
};
}()
};
// Using the jQuery ready event is excellent for ensuring all
// code has been downloaded and evaluated and is ready to be
// initialized. Treat this as your single entry point into the
// application.
jQuery(function($) {
$(document).ready(function(){
var foo = new Application.module('Chat').Collection();
});
});
// Filename: chat-module.js
(function(chat){
chat.Model = Backbone.Model.extend({ ... }),
chat.Collection = Backbone.Collection.extend({ ... }),
})(Application.module('Chat'));
It seems well but if try to define chat module for example and invoke it later I have the following error:
Uncaught TypeError: Property 'Collection' of object #<Object> is not a function
I think that error due jQuery ready invokes when chat-module.js not available yet.
How can I resolve that problem?
Your code creates an object and assigns it to the global variable chat, which has a module function as a property:
var chat = {
module: function...
};
...but then when you use it, you use Application.module rather than chat.module.
Application.module('Chat')
and
var foo = new Application.module('Chat').Collection();
It seems to me that your chat variable should be called Application.
Also note that you're using module in two different ways, both with new and without. Without would be the correct use based on your code. It will work both ways because module returns a function (which is an object), and so that will override the normal new behavior, but it means that using new serves no purpose and is misleading to someone reading the code.

Javascript scope issue, inside an anonymous function

Sorry I couldn't be anymore specific with the title.
I'm building a web-site (personal), which displays different content to the user depending on the query string that is used in the url.
e.g. page=home.html would display home.html
The websites Javascript is wrapped inside an object, with each value containing different data, some pseudo code:
(function(){
var wrapper = {
init: function(){
//Runs on document ready
this.foo();
this.nav.render();
},
foo: function(){
//Some functionality goes here for the website, e.g. Display something from an API
},
nav: {
//Functionality to handle the navigation, has different properties
config: {
//Contains the config for nav, e.g. page names + locations
dir: '/directory/to/content/',
pages: {
page_name: wrapper.nav.config.dir + 'page_value'
}
},
render: function(){
//some code
},
routes: function(){
//some code}
}
}
};
$(function(){
wrapper.init();
});
})();
My problem is that I'm trying to prepend the dir value to each of the page values (inside the object where the pages are defined), expecting to get the output of (in this pseudo code case) of directory/to/content/page_value, but instead dir is undefined when I'm trying to access it, I've tried the following to achieve what I want:
wrapper.nav.config.dir + 'page_value'
I've been playing around with the last 30 minutes trying to find out what I'm doing wrong, and even thought about hard-coding the URL in for each page.
The reasoning for wanting to do this is that my local development server and web host have different directory structures, so I don't want to re-write the URL's each time I want to develop + publish. As for why everything is wrapped inside an object, I thought it would be easier to maintain this way.
Hopefully the answer is simple and it's just an amateur mistake / lack of understanding.
The issue is that you can't refer to a variable that is being defined in that very definition.
So, inside the definition of wrapper, you can't refer to wrapper. And, inside the definition of config, you can't refer to config either and so on.
The usual design pattern for solving this is to initialize as much as you can in the declaration of your data structure and then do the rest in .init() when you can freely access all of it.
Change the first two lines to:
var wrapper = null;
(function(){
wrapper = {
Otherwise, the wrapper is a local variable to your anonymous function.
The problem is that you're still busy defining the wrapper when you ask for its value, which is why it's still undefined.
The code below fails too:
var x = {
y:"1",
z:x.y
}
Why not:
//...
init: function(){
//Runs on document ready
this.foo();
var config = this.nav.config;
for (var page in config.pages) {
config.pages[page] = config.dir + config.pages[page];
}
},
//...

Categories