I use RequireJS to load my modules in one of my projects.
I see around the web different ways to require modules using the require
call (and not define
).
Lets assume I have a module named "JQuery" and I would like to require it. Two ways are possible as I saw in examples:
This:
require(["JQuery"], function($){
$.doSomething();
})
And this:
var $ = require("JQuery");
$.doSomething();
My question is if the load is async as RequireJS documantation says it is, how can the second convention work? How can I say for sure that $
is defined and that the first row completed before the second row executes?
RequireJS, like LABjs, allows for asynchronous JavaScript loading and dependency management; but, RequireJS uses a much more modular approach to dependency definitions. This is just an initial exploration of RequireJS. RequireJS seems to be quite robust and includes optimization and "build" tools for deployment.
The whole process of requiring/loading a module is synchronous. That's why we were able to see the modules fully loaded after one cycle of the event loop.
JavaScript is Synchronous Spoiler: at its base, JavaScript is a synchronous, blocking, single-threaded language. That just means that only one operation can be in progress at a time.
RequireJS uses Asynchronous Module Loading (AMD) for loading files. Each dependent module will start loading through asynchronous requests in the given order. Even though the file order is considered, we cannot guarantee that the first file is loaded before the second file due to the asynchronous nature.
RequireJS always loads modules asynchronously but it allow a form of require
that looks synchronous. Your second snippet is actually missing some really important code. (Also, the module name for jQuery is hardcoded to jquery
. You could write a configuration that allows you to refer to it as jQuery
but there's no point.) This form of the require
calls is designed to be used inside modules so:
define(function (require) {
var $ = require("jquery");
$.doSomething();
});
What RequireJS does with the code above is transform it into this before executing it:
define(['jquery'], function (require) {
var $ = require("jquery");
$.doSomething();
});
Note the addition of the dependency as the first argument of define
. When RequireJS executes the code, it finds the dependency, loads jquery
and then calls the anonymous function. By the time require("jquery")
is encountered the module is already loaded. At the end of the day while the require
call looks synchronous, the loading of the module it requires still happens asynchronously.
Can you use this synchronous form require
outside of a define
call? Only if you are okay with failures. This require
call will fail if the module passed to it is not already loaded. You get the infamous error:
Module name ... has not been loaded yet for context: ...
Using it in a define
like I've shown above is safe. Or I guess you could do:
require(['jquery'], function (require) {
var $ = require("jquery");
$.doSomething();
});
which would work but what's the point of manually repeating the dependency. (In case you wonder, RequireJS does not transform a require
call with a callback like the one I have in my example here in the same way it transforms a define
call as I've shown above.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With