I have a module defined as follows:
define(
['backbone', 'View/Sidebar', 'View/ControlBar'],
function() {
...
}
);
In that module there is a method called loadView, which assigns a variable as follows:
loadView: function(name, bootstrap_function, into) {
var _class = require('View/'+name);
...
}
So, we can see that both View/Sidebar and View/ControlBar are being loaded by the define call (first arg). When I use require('Sidebar'), I get no errors, yet if I use require('ControlBar') I do get the notorious:
Error: Module name "View/ControlBar" has not been loaded yet for context: _
(http://requirejs.org/docs/errors.html#notloaded)
I have re-written, copied and pasted, verified that it is loaded in Firebug and so on but cannot for the life of me work out why I am getting this error 100% of the time.
I think this has something to do with how the arguments are called for require. I have found that the following throws an error
define(
['mymodule1', 'mymodule2'],
function(mod1, mod2) {
...
var x = require('mymodule2');
...
}
);
Whereas the following does not:
define(
['mymodule1', 'mymodule2'],
function() {
...
var x = require('mymodule2');
...
}
);
The difference is whether or not the loaded modules are declared as arguments to the function or not. At least this is the way that it seems to me, it does not, however, make much sense...
Related
I'm trying to figure out how to use the browser-based aws-sdk.js with require.js when building a web app.
If I try to build a class and include aws-sdk in the require.js define, once I try to create an instance and reference the AWS class, it says it is undefined.
For example, I have a function that checks to see if the credentials are an instance of AWS.Credentials and if not, it tries to initialize it with an STS token it retrieves via Rest.
The problem is, the code dies on the if(this.credentials instanceof AWS.Credentials) saying AWS is undefined. It even dies on my simple check of the needsRefresh.
This is what my define looks like - I'll include the 'needsRefresh' wrapper for an example of the sort of thing that is throwing the Undefined error:
define(['require','aws-sdk','jquery'],
function (require, AWS, $) {
// Aws helper class
function AwsHelper() { };
AwsHelper.prototype = {
credentials: null,
tokenNeedsRefresh: function () {
//////////////////////////////////////////////////////////////////
// errors out on the following line with: //
// TypeError: Cannot read property 'Credentials' of undefined //
//////////////////////////////////////////////////////////////////
if(this.credentials instanceof AWS.Credentials) {
return this.credentials.needsRefresh();
} else return true;
}
};
return AwsHelper;
}
);
I also tried the following format at the top of the file:
define(function (require) {
var AWS = require("aws-sdk"),
$ = require("jquery");
/* .. */
If I remove all onLoad references to the refresh code running, it will load and I can create an instance. But as soon as I call any function that references the AWS class, it dies.
How do I make sure that AWS class definition is still in global space once an instance is spawned?
Dunno what difference the paths will make (it's finding and loading the code just fine - I can see AWS Class in namespace in the debugger as it's loading but it's not in the namespace on the function call), but added on request:
requirejs.config({
baseUrl: '/js',
paths: {
lib: 'lib',
ImageUploader: 'ImageUploader'
}
});
I decided to try to play with this again and seemed to have figured out how I was going about it incorrectly. I have yet to integrate it back into my existing code setup, but I think I have a working solution.
The thing I was doing wrong was I was trying to set up the AWS class so I could load it as a module (thus why I tried wrapping it as the require.js suggested).
Playing with it this time around, I noticed something I hadn't before. I had an AWS that was undefined in the local scope and an other AWS that held the class definition in the global scope. So it was trying to specify AWS in my define that was creating the local 'null' version:
define(
["jquery","aws-sdk","dropzone","app/MyUtilities"],
function ($, AWS, Dropzone, MyUtilities) {
"use strict";
function MyClass() {};
return MyClass;
}
);
jquery and dropzone have whatever is needed to make sure they load that way, but aws-sdk seems to do some of it's own asynchronous loading. Thus the scope variable in the function is undefined.
Technically, it seems the only thing I needed defined as a module in the function wrapper is my own utilities module. So by switching it to:
define(
["app/MyUtilities","jquery","aws-sdk","dropzone"],
function (MyUtilities) {
"use strict";
function MyClass() {};
return MyClass;
}
);
... it seems $ and jquery are defined as needed, Dropzone is defined as needed and AWS is defined as needed. (and I don't get my errors when accessing the static AWS.config or AWS.Credentials definitions as I did before)
here, I am attempting to set value for read-only property but I am not getting any error:
HERE IS MY CODE:
require('use-strict');
function Employee(firstname) {
var _firstname = firstname;
Object.defineProperty(this, 'firstName', {
get: function () { return _firstname },
//set: function (value) { _firstname = value }
});
}
var employee = new Employee('Fawad');
employee.firstName = 'Yasir'; //Attempting to set a value for read-only property.
console.log(employee.firstName);
From the documentation for the use-strict package:
The implementation works by patching Node's internal module.wrapper
array, and then freezing it, so that further modifications are not
possible.
Also, this means that the current module will not be affected. You
should still "use strict" in the module that does
require('use-strict'). This module applies strictness to all future
modules loaded by your program.
Use of "use strict"; at the top of page worked for me although this approach is usually used for JavaScript development. I was trying to use one of the node.js packages which didn't worked.
I have a module which is dependent upon both, PhotoSwipe and PhotoSwipeUI_Default. I am requiring both modules, like so and inside of my module I am initialising my gallery. EG:
define("modules/lightboxStart", ["vendor/PhotoSwipe", "vendor/PhotoSwipeUI_Default"], function (PhotoSwipe, PhotoSwipeUI_Default) {
var StartGallery = function(){
var lightBox = new PhotoSwipe($pswp, PhotoSwipeUI_Default, items, options);
lightBox.init();
}
StartGallery()
}
The gallery then works as expected but require is throwing a mismatched anonymous define module error in PhotoSwipe.js.
After looking through the docs I came to the conclusion that I need to run both scripts(PhotoSwipe and PhotoSwipeUI_Default) through the require.js API.
I then defined each, like so:
define('PhotoSwipe', function() {
//PhotoSwipe script here
return PhotoSwipe
})
And
define('PhotoSwipeUI_Default', function() {
//PhotoSwipeUI_Default script here
return PhotoSwipeUI_Default
})
This then eliminates the mismatched anonymous define module error I was getting earlier, but I am getting this error now instead:
PhotoSwipe is not a function
How could I fix this? I am essentially trying to access the PhotoSwipe function within PhotoSwipe.js and pass through my arguments but I am unable to do so without generating a load of js errors on the page and I can not figure out why.
Help much appreciated!
define( ["modules/lightboxStart", "vendor/PhotoSwipe", "vendor/PhotoSwipeUI_Default"], function (lightboxStart, PhotoSwipe, PhotoSwipeUI_Default) { //i think so}
I have some module like this:
define('hello',[],
function()
{
return {
say: function(word) { console.log("Hello, "+word) },
};
});
And I'm using it like this (without any require.config) :
require(["hello"],
function(hello)
{
console.log("main",hello);
hello.say("main");
});
So far, so good.
But when I'm trying to require the same module with an absolute path, I've got my dependence module undefined:
require(["http://example.com/js/hello.js"],
function(hello)
{
console.log("main",hello);
hello.say("main");
});
Console:
main undefined
Uncaught TypeError: Cannot read property 'say' of undefined // Oops!
Why is it so?
Named module (define("NAME", [ ... ], function() { ... })) is meant to be required under exact that name. When it is required with a URL it is loaded correctly, but registers itself under its "desired" name, after which requirejs loses track of it still looking for a module with a name http://example.com/js/hello.js.
The reason the name given to define() isn't overriden with the one under which the module was required is to allow multiple module definitions to coexist in the file, for example after optimization. Optimizer will convert all define calls to the form with explicit name.
The reason the absolute name isn't converted to a module id is that this conversion is impossible. All the configuration options of requirejs determine how to convert module id to script location, not other way around.
Documentation discourages use of the named modules:
These are normally generated by the optimization tool. You can explicitly name modules yourself, but it makes the modules less portable ... It is normally best to avoid coding in a name for the module and just let the optimization tool burn in the module names...
Anonymous module, i.e.:
define([],
function()
{
return {
say: function(word) { console.log("Hello, "+word) },
};
});
works with either module id ("hello") or absolute path, because it is first registered without a name and later receives the name under which it was required.
I am playing around and learning about vows with a personal project. This is a small client side library, with testing done in vows. Therefore, I must build and test a file that is written like this:
(function(exports) {
var module = export.module = { "version":"0.0.1" };
//more stuff
})(this);
In my testing (based off of science.js, d3, etc.) requires that module like so:
require("../module");
I continued to get a "module not defined error" when trying to run the tests, so I went to a repl and ran:
require("../module")
and it returned:
{ module: { version: "0.0.1" } }
I realize I could do something like:
var module = require("../module").module;
but feel like I am creating a problem by doing it that way, especially since the libraries that I based this project on are doing it in the format I described.
I would like for my project to behave similar to those which I based it off of, where:
require("../module");
creates a variable in this namespace:
module.version; //is valid.
I have seen this in a variety of libraries, and I am following the format and thought process to the T but believe I might be missing something about require behavior I don't know about.
There is no problem creating it this way. Modules define what they return in the module.exports object. By the way, you don't actually need self executing functions (SEF), there is no global leakage like in browsers :-)
Examples
module1.js:
module.exports = {
module: { 'version': '0.1.1' }
};
main.js:
var module1 = require( './module1.js' );
// module1 has what is exported in module1.js
Once you've understood how this works, you can easily export the version number right away if you want to:
module1.js:
module.exports = '0.1.1';
main.js:
var module1 = require( './module1.js' );
console.log( module1 === '0.1.1' ); // true
Or if you want some logic, you can easily extend your module1.js file like this:
module.exports = ( function() {
// some code
return version;
} () ); // note the self executing part :-)
// since it's self executed, the exported part
// is what's returned in the SEF
Or, as many modules do, if you want to export some utility functions (and keep others "private"), you could do it like this:
module.exports = {
func1: function() {
return someFunc();
},
func2: function() {},
prop: '1.0.0'
};
// This function is local to this file, it's not exported
function someFunc() {
}
So, in main.js:
var module1 = require( './module1.js' );
module1.func1(); // works
module1.func2(); // works
module1.prop; // "1.0.0"
module1.someFunc(); // Reference error, the function doesn't exist
Your special case
About your special case, I wouldn't recommend doing it like they're doing.
If you look here: https://github.com/jasondavies/science.js/blob/master/science.v1.js
You see that they're not using the var keyword. So, they're creating a global variable.
This is why they can access it once they require the module defining the global variable.
And by the way, the exports argument is useless in their case. It's even misleading, since it actually is the global object (equivalent of window in browsers), not the module.exports object (this in functions is the global object, it'd be undefined if strict mode were enabled).
Conclusion
Don't do it like they're doing, it's a bad idea. Global variables are a bad idea, it's better to use node's philosophy, and to store the required module in a variable that you reuse.
If you want to have an object that you can use in client side and test in node.js, here is a way:
yourModule.js:
// Use either node's export or the global object in browsers
var global = module ? module.exports : window.yourModule;
( function( exports ) {
var yourModule = {};
// do some stuff
exports = yourModule;
} ( global ) );
Which you can shorten to this in order to avoid creating the global variable:
( function( exports ) {
var yourModule = {};
// do some stuff
exports = yourModule;
} ( module ? module.exports : window.yourModule ) );
This way, you can use it like this on the client-side:
yourModule.someMethod(); // global object, "namespace"
And on the server side:
var yourModule = require( '../yourModule.js' );
yourModule.someMethod(); // local variable :-)
Just FYI, .. means "parent directory". This is the relative path of where to get the module. If the file were in the same directory, you'd use ..