RequireJs dependency always undefined - javascript

I am using require Js and am getting rather confused as to why my modules are loading but dependencies are always undefined and even upon using require.defined() function to check if my module has been loaded it indeed has been but when I use the require([deps], function(deps){}); all of my dependencies are undefined (except for jquery, underscore and knockout)
my file structure is as follows
my file structure is as follows
scripts
|
|
main.js
|
|_________BusinessScripts
| |
| |
jquery.js |
| |
| boostrapper.js-undefined
ko.js |
|
dataservice.js-undefined
here is an example of my main file that kicks off require
requirejs.config(
{
paths: {
'jquery': 'jquery-1.7.1',
'underscore': 'underscore',
'ko': 'knockout-2.2.1'
},
shim: {
underscore: { exports: '_' },
}
}
);
requirejs(['require', 'BusinessScripts/bootstrapper', 'BusinessScripts/dataservice'],
function (require,bootstrapper, dataservice) {
var def = require.defined('BusinessScripts/bootstrapper'); //this returns true
if (dataservice !== undefined) { // always undefined
alert("Loaded properly");
} else {
alert("not loaded!!!");
}
if (bootstrapper !== undefined) { // always undefined
alert("Loaded properly");
} else {
alert("not loaded!!!");
}
});
my data service class does a quite lengthy jquery get but as a simple example my bootstrapper is doing next to nothing
//bootstrapper
define(function () { var one = 1;
var run = function () {
}
});
//dataservice
define(['jquery', 'underscore'],function ($, _) {
$.ajax({lengthy work...});
});
as I said both modules are being loaded but are never resolving
any help would be much appreciated.

You're not returning anything from your bootstrapper or dataservice modules, so the "public" part of the module is undefined. RequireJS simply executes body of the define function and returns undefined implicitly. I think a good analogy is to think of a module as a black box with all internals hidden, only allowing access through the public interface (which is whatever you return from module's final return statement)
You should rewrite your modules a bit, for example:
bootstrapper.js
define(function () {
var one = 1;
var run = function () {
console.log('Running...');
}
return {
publicRun: run,
publicOne: one
}
});
dataservice.js
define(['jquery', 'underscore'],function ($, _) {
$.ajax({
// lengthy work...
});
return 'Lengthy work started!';
});
Then you could use these modules like this:
requirejs(['require', 'BusinessScripts/bootstrapper', 'BusinessScripts/dataservice'],
function (require, bootstrapper, dataservice) {
// prints "1"
console.log(dataservice.publicOne);
// prints "Running..."
dataservice.publicRun();
// prints "Lengthy work started!"
console.log(bootstrapper);
});
The official docs covers the topic of defining modules in detail, I'd recommend reading as much documentation as possible before diving in.

This answer doesn't fully 'match' the question's (specific) circumstance, but it may help someone for the (general) question - Why is my dependency undefined?
Tip: Double check that your dependency isn't dependent on the thing you're trying to get dependent on...
i.e. If you want A to depend on B, double check that B isn't depending on A.

Related

Prevent function name to get mangled while minification

I'm using gulp-uglify ~1.5.4 for my javascript minification, in a file a have this code : columns[j].colDef.cellRenderer.name === 'dateRenderer', cellRenderer is a function so cellRenderer.name will return he name of that function.
So when the function is dateRenderer() that code should return true which doesn't happens since after the minification the function got mangled.
I found this thread : Make gulp-uglify not mangle only one variable but I don't want to tell uglify what variables to mangle and not, isn't there any other way to solve this ? like in AngularJS we are using the $inject service.
If you don't want to specify to uglifyjs what function names should it skip from mangling, store that function's name as a string.
function dateRenderer() {
// do something useful
}
dateRenderer.rendererName = 'dateRenderer'
// later ...
var fn = dateRenderer
if (fn.rendererName === 'dateRenderer') {
console.log('ok!')
}
...or set its name after you called that specific function:
function dateRenderer() {
dateRenderer.rendererName = 'dateRenderer'
// do something useful
}
// later ...
var fn = dateRenderer
// do something
dateRenderer()
if (fn.rendererName === 'dateRenderer') {
console.log('ok!')
}

UMD pattern for angular directive

I'm looking to open source an angular directive on npm and I'm trying to come up with the most universal pattern for doing so. How's this? I have 3 questions:
!function(name, make) {
make = make()
// 1. Is this line needed?
var angular = require('angular')
// 2. Is this line needed?
angular.module(name, []).directive(name, make)
if (typeof module != 'undefined') module.exports = make
else this[name] = make
// 3. Is this line needed?
if (typeof define == 'function') define(function() { return make })
}('exampleDirective', function() {
return function() {
return {
link: function (scope, label, atts) {}
}
}
});
Is require('angular') needed or is it safe to assume the angular variable exists?
Is it necessary to call angular.module and angular.directive in my definition or should only the consuming app(s) do this?
Do AMD environments need this or does the module.exports or global suffice?
1
// 1. Is this line needed?
var angular = require('angular')
No. Applications that use your library must always import their own version of AngularJS.
2
// 2. Is this line needed?
angular.module(name, []).directive(name, make)
Yes. Applications will need to list your module name in their list of dependencies like this:
var myApp = angular.module('myApp',[name]);
3
// 3. Is this line needed?
if (typeof define == 'function') define(function() { return make })
}('exampleDirective', function() {
return function() {
return {
link: function (scope, label, atts) {}
}
}
});
No. You can just put the directive on the module and other developers will be able to use it.

Is there any downside to using $injector.get() to get my dependencies in Angular?

My team wants to move to a style of dependency injection that is closer to the CommonJS/Node JS syntax for out Angular codebase:
var myDependency = require('myDependency');
I've started using $injector.get() directly inside at the top of my functions, so far with no obvious trouble. That means I've converted this:
angular.module('modD', ['modA', 'modB', 'modC'])
.service('serviceD', ['serviceA', 'serviceB', 'serviceC', function(serviceA, serviceB, serviceC) {
//My code here
}])
Into:
angular.module('modD', ['modA', 'modB', 'modC'])
.service('serviceD', ['$injector', function($injector) {
var serviceA = $injector.get('serviceA');
var serviceB = $injector.get('serviceB');
var serviceC = $injector.get('serviceC');
//My code here
}]);
Is there something I'm missing. Does not declaring the required dependencies outside of the function definition cause any sort of performance issues?
Note: this answer has not been tested.
After digging into the angular's code, I find this:
// in function createInjector
function provider(name, provider_) {
...
if (isFunction(provider_) || isArray(provider_)) {
provider_ = providerInjector.instantiate(provider_);
}
...
return providerCache[name + providerSuffix] = provider_;
}
...
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
...
// in function createInternalInjector
function invoke (...){
...
for (i = 0, length = $inject.length; i < length; i++) {
args.push(
locals && locals.hasOwnProperty(key)
? locals[key]
: getService(key, serviceName)
);
}
...
return fn.apply(self, args);
}
function instantiate(...){
...
var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);
var returnedValue = invoke(Type, instance, locals, serviceName);
return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
}
...
return {
invoke: invoke,
instantiate: instantiate,
get: getService,
annotate: createInjector.$$annotate,
has: function(name) {
return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
}
};
Its calls seems like:
service invoked factory invoked instantiate
factory invoked provider invoked instantiate
So I think your questions is equal to Is calling $injector.get() one by one has the same performance as calling $injector.instantiate() once?
As the code shows, instantiate invoked invoke which actually invoked getService for each services injected by you. And $injector.get is just binding to getService.
So the answer to my equal question is True.
And the answer to your question is No, their performance is very close.
Please correct me if I'm wrong, thank you!
There are no significant difference between both pieces of code in the case of a service. $injector.get(...) call doesn't provide any overhead. But it provides a significant amount of extra characters per dependency.
There is a difference when the same thing is done with injectables that have local dependencies - controllers and route/state resolvers.
When these dependencies
app.controller('SomeCtrl', function ($scope, service) { ... });
are replaced with $injector.get(...), it will choke on $scope - it is local dependency. And with other dependencies being retrieved like that, controller loses its testability. The dependencies cannot be mocked with
$controller('SomeCtrl', { service: mockedService });
I personally don't see how $injector.get(...) may benefit the style of the project (and haven't seen a good style guide that would suggest it).
Node uses require function because it works for it, not because it is better or cooler. The alternative would be to pack each Node script into into AMD-like wrappers, which would be painful. Fortunately, we already have wrappers around Angular units!

requirejs loading same module twice

I'm using the single-page app template from https://github.com/volojs/create-template
I tried to make a simple example below.
Problem
ModuleA.js is being loaded twice, once directly from main.js and again from simulator.js which depends also on that module. This is causing two different references to an object (which I thought would only be one, like a singleton). I thought requirejs would not load the same module twice. Being (relatively) new to JavaScript I realize this may be naivete on my part. I'm trying to follow the template.
Here's a simplified version that demonstrates the problem:
www/index.html
<head>
...
<script data-main="app" src="lib/require.js"></script>
</head>
...
www/app.js
// For any third party dependencies, like jQuery, place them in the lib folder.
// Configure loading modules from the lib directory,
// except for 'app' ones, which are in a sibling
// directory.
requirejs.config({
baseUrl: 'lib',
paths: {
app: '../app'
}
});
// Start loading the main app file. Put all of
// your application logic in there.
requirejs(['app/main']);
www/app/main.js
define(function (require) {
var simulator = require('./simulator.js');
var ModuleA = require('./ModuleA.js');
ModuleA.init();
ModuleA.displayList();
ModuleA.update("joe", 99);
ModuleA.displayList();
simulator.start(); // should display the same list
});
www/app/ModuleA.js
define(function () {
var theList = {};
console.log("loading ModuleA");
return {
displayList: function () {
console.log(Object.keys(theList));
},
init : function () {
theList["fred"] = 10;
},
update : function (k, v) {
theList[k] = v;
}
}
});
www/app/simulator.js
define(["./ModuleA"], function (ModuleA) {
return {
start: function () {
ModuleA.displayList();
}
};
});
console output:
loading ModuleA
loading ModuleA
["fred"]
["fred", "joe"]
[]
The empty [] displayed on the last line is (likely) the second copy of the list due to the second loading of ModuleA.
The problem is the module references are not consistent. In main.js it requires ./ModuleA.js whereas in simulator.js it defines ./ModuleA (without the .js filetype).
Making those references identical corrects the behavior such that the module is only loaded once.
I guess I mixed the styles because of the many examples on the web. It kind of seems like a bug that it works this way, but maybe it's a feature?
If you want to share an instantiated singleton object using requireJS, you can do something like this for ModuleA:
define(function () {
console.log("loading ModuleA");
function myList(){
this.theList = {}
}
myList.prototype.displayList = function () {
console.log(Object.keys(this.theList));
}
myList.prototype.init = function () {
this.theList["fred"] = 10;
}
myList.prototype.update = function (k, v) {
this.theList[k] = v;
}
return new myList();
});

requirejs and ByteBuffer

im an javascript newbie and google didnt helps:
I tryed to load ByteBuffer.js in an require.js module:
define(['js/ByteBufferAB'], function (ByteBufferAB) {
var MessageBase = function () {
this._version = 0; // unsinged int 16 bits
this._dataType = "";
};
MessageBase.prototype.toBytes = function () {
//console.log( new ByteBufferAB(58));
var headerBytes = new ByteBufferAB(58); // <-- here comes the error
headerBytes.clear();
return headerBytes;
};
return MessageBase;
});
with the same syntax math.js is properly loaded.
But with ByteBufferAB.js the following error comes:
Uncaught TypeError: undefined is not a function
What am I doing wrong?
Thank you for your help
In your define call you refer to the module as js/ByteBufferAB so RequireJS looks for a module named js/ByteBufferAB. However, the module defines itself as ByteBuffer:
/* AMD */ else if (typeof define === 'function' && define["amd"])
define("ByteBuffer", ["Long"], function(Long) { return loadByteBuffer(Long); });
Because the module name is hardcoded, you need to have a mapping like this in your paths in the configuration you give to RequireJS:
ByteBuffer: "js/ByteBufferAB"
and you need to refer to the module as ByteBuffer in your define call.
None of this would be required if the developers for this library had not hardcoded a name but they have, and so here we are.

Categories