In a script associated with an Orchard view I try to post an AJAX to server with dojo.request.post function. However, I only get esri/request, dojo/request is undefined. I call the request outside the function where the require statements reside, but there's no problem with other required packages as long as I use them in correct format. Dojo/request works in our other project, so I suspect Orchard of messing things up (the other project's dojo/request use is in a plain page, not in a view), though I would expect problems caused by it to surface earlier.
Important parts of the code:
require([ ... "dojo/request", ... ], function (... Request, ...) {
//custom init function contents
})
function sendResults(featureSet) {
//custom code processing the parameter, making uri, JSON and like
dojo.request.post(uri, {
//sending data
})
}
My razor require part in the same file contains:
Script.Require("esri/JavaScriptApi").AtHead();
Script.Require("dojo").AtHead();
Those are defined in resourcemanifest.cs:
manifest.DefineScript("esri/JavaScriptApi").SetUrl("http://js.arcgis.com/3.14/");
manifest.DefineScript("dojo").SetUrl("//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js");
The error I get when I try to run the code:
TypeError: dojo.request is undefined
I've tested it in FireBug and confirmed that dojo/request doesn't exist (the same for variants, like dojo/Request), only esri/request is a function, but it has no post method.
I'm stuck here. Google search lead to "plains of sheer desperation" (page 5+) with no useful output and my co-workers don't know. Does anyone know why I can't see dojo/request and how to get it?
As far as I'm aware, dojo/request does not export a global (as modern AMD modules generally shouldn't need to), so dojo.request would never work in any context.
The appropriate way to use AMD modules is to use them within the body of a require callback (or, even better, organize your own code in AMD modules as well, and use them within a define factory function).
require([ ... "dojo/request", ... ], function (... request, ...) {
request.post(...);
})
Alternately, if you're certain dojo/request has been loaded by the time you want to use it, you could use single-argument require to reference it:
require('dojo/request').post(...);
However, this is typically not ideal and seen as a hack.
Perhaps the Introduction to AMD Modules tutorial would help to better understand optimal AMD usage.
Related
I've been reading about es6 module loaders and I just don't quite understand how it works and am hoping someone can enlighten me.
In the practical workflows link above they have an example like this
System.import('app/app').then(function(app) {
// app is now the Module object with exports as getters
});
No problem with that - I get it. But then I see stuff like this
var $ = require('jquery');
and get really confused. What happens if at the time of this call jquery has not yet been transferred to the browser? Does the thread just spin? Does the browser parse your script behind-the-scenes and reform it into a callback like RequireJs does? Is what it does configurable? Are there specific limitations?
Can someone give me a rundown?
The ES6 Module Loader will fetch the source, determine dependencies, and wait until those dependencies have loaded before executing the module. So by the time the require executes, the dependency is already sitting there waiting to be executed.
When loading CommonJS through an ES6 module loader, we rely on statically parsing out the require statements from the source, and only executing the source once those requires have loaded.
In this way we can support CommonJS in the browser loaded dynamically. Circular references are treated identically to the way they are handled in Node.
The regular expressions parsing out the require are actually pretty reliable and quick, while taking into account comments and surrounding tokens. See https://github.com/systemjs/systemjs/blob/master/lib/extension-cjs.js#L10 for the one used by SystemJS.
There is one remaining limitation with this approach and that is dynamic and conditional CommonJS requires like if (condition) require('some' + 'name') aren't detected properly. This is a necessary cost though to make CommonJS behave as a fully asynchronous module format in the browser.
I am using requireJS 2.x. I found out that some tutorials (and the official docs) sometimes use
requirejs.config({ [...] });
requirejs(["module"]) ...
and sometimes
require.config({ [...] });
require(["module"]) ...
Is there any difference between those two functions (require and requirejs)? I could not find any word about that in the docs. :(
They are exactly the same.
The reason is some environments might already have a require, in which case RequireJS doesn't overwrite it and allows usage of the library through requirejs
See this commit - https://github.com/jrburke/requirejs/commit/be45948433b053921dc6a6a57bf06d04e13b3b39
Are requirejs And require the Same?
As of RequireJS 2.1.15, require and requirejs in the global space are indeed "exactly the same", as can be evidenced by this test you can perform in the console:
> require === requirejs
true
That the test returns true tells you they are the exact same function object. They are not two functions that happen to have similar or identical code. They are the same object, period.
Note, however when you execute define(['require'], function (require) { The require passed to the function is normally different from the global require.
Should You Use require or requirejs?
It depends. RequireJS is an AMD loader but it is not the only loader in town. If you want to write code that conforms 100% to the AMD spec, so that someone using your code can use whatever loader they want without having to modify your code, then you should use require at the global level, because requirejs is specific to RequireJS. Another AMD loader won't define it. The AMD spec defines require but not requirejs.
If you are loading something else that defines a global require then you have to use requirejs at the global level to avoid conflict.
Inside a module, always use define to obtain a reference to require. You should do this quite irrespective of whether there is a conflict in the global space.
OK, they may indeed be "exactly the same". Let's then focus on why you would use one versus the other...
What is unclear is what should be considered "best practice": If requirejs provides extra assurance "if some environments might already have a require", then wouldn't it be a good idea to always use the requirejs function to define a require configuration rather than the require function?
Also, what happens if the unthinkable happens and the environment in question not only already has a "require" defined but also has a "requirejs" defined? Does that mean we should have a requirejsjs too? And so on...?
They are Same
Open website which loaded require already
then open Chrome console
type require in console and press enter
type requirejs in console and press enter
you can find that they are same function with different names
require.js states the way of defining objects inside modules with define([requiremens], object) as best way.
So every page, or other js file, will do require() call and receive modules as parameters.
This works pretty fine, each function/module has own namespace.
The problem is that I have:
// AJAX/Requests.js
define(['UI/Message'],function(Message){
var Requests={
checkResponse:function(response){
//1==ok
//0==error
//2==good message
//3==good message, but still stop
if(response.status==1){
return true;
}
else if(response.status==2){
Message.good(response.message);
return true;
}
else if(response.status==3){
Message.good(response.message);
return false;
}
else{
Message.bad(response.message);
return false;
}
}
};
return Requests;
});
Now the UI/Message is defined in the same way, and it returns object.
But when I edit file with requests, I can't navigate by code, so if I want to edit Message object, the only way is to go and open file the myself and to find function I need, rather than have the IDE jump there for me.
Is there some workaround for pycharm specifically or to require.js in common to solve this issue? When you have a lot of code it becomes a mess to navigate it, which is why I use an IDE in the first place!
And what worse: The editor never knows what functions objects have!
The one possible solution I can see is to not to use enclosed namespaces, and to declare global variable before the define() call, but in this case all objects shall be called like UI_Message, AJAX_Requests. In order to be sure, that I don't have some Message in two different locations....
And I am not sure, if require.js optimizer will use this correctly. Require.js documentation states very clear, to stay away from global variables.
It's a known issue, please star/vote.
From the issue description:
The dojo library switched to AMD's format define() for loading modules
instead of dojo.require(). Previously I was able to use Ctrl+B on
dojo.require('path.to.someJs') to jump to the declaration. This does
not work on the new format define(['path/to/someJs]', ...).
As PyCharm, WebStorm, PhpStorm and IntelliJ IDEA share the same JavaScript plug-in, this issue also applies to the product that you are using. You will continue to observe the described problem until this bug is fixed. Sorry for the inconvenience.
WebStorm (at least 6.0.2) supports code navigation with RequireJs if you're defining your modules with the CommonJs wrapper and use the exports and module arguments:
//foo.js
define(function(require, exports, module) {
//use exports to expose properties for code navigation in other modules
exports.bar = function() {}
});
Apparently, it works even if the module using it doesn't use the CommonJs wrapper format:
define(['./foo'], function(foo) {
foo.bar(); //code navigation works here
}
If the other IDEs use the same JavaScript plug-in as CrazyCoder said, it may work on their newer releases as well.
I’m currently testing various asynchronous-resource-loaders to see which one I want to use. At the moment Curl is throwing a ‘Promise already completed’ error…and their documentation says ‘this should never happen’.
I “suspect” I must to use a ‘define’ within each file being loaded (hope not). Further, their documentation says Curl can work with non-AMD javascript files. But...I am new to AMD and since Curl is far-faster than the other ones I'm testing...I am willing to put some time into understanding this better.
Lastly...
Even though FireBug shows the errors...all the files STILL LOAD asynchronously! But, BECAUSE there are errors...the 'then' portion of the code never gets called.
So My Questions Are:
Do I have to update all the JavaScript file-objects to be contained in a 'define'? (...hope not)
Can you see any other problem syntactically?
The Head’s Code Looks Like This:
<script type="text/javascript">
///<summary>Configuration</summary>
curl = { baseUrl: 'Includes/JavaScript/' };
</script>
<script src="Loaders/Curl/curl.js" type="text/javascript"></script>
<script type="text/javascript">
function onSuccess() {
}
function onError(ex) {
//alert(ex);
}
require(["MooTools/Core/mootools-1.2.2-core-jm",
"MooTools/mGeneral",
"jQuery/Core/jquery-1.3.2",
"jQuery/Core/jquery.tools.min",
"jQuery/ThirdPartyPlugIns/jquery.tmpl"])
.then(onSuccess, onError);
//require(["jQuery/TopUp/top_up-min"], null);
require(["jQuery/ThirdPartyPlugIns/jquery.dimensions",
"jQuery/ThirdPartyPlugIns/jQuery.Color.Animations",
"jQuery/ThirdPartyPlugIns/jquery.corners.min",
"jQuery/ThirdPartyPlugIns/jquery.tipsy",
"jQuery/ThirdPartyPlugIns/jquery.numberformatter-1.1.0",
"jQuery/ThirdPartyPlugIns/jquery.tipsy"]);
require(["general",
"WindowCenter",
"ThirdPartyPlugin/KeyBoardCapture",
"ThirdPartyPlugin/bsn.AutoSuggest_2.1.3",
"ee/8Ball",
"ee/EE"]);
</script>
Again...I'm sure it is caused by inexperience with AMD-styled code, but I still need help...so any is appreciated.
Typically, you should wrap your modules in a define() or append a define() at the end of the file if those modules have no dependencies. It seems, though, that those modules all depend on jQuery, if not other modules/files.
Since you're not using standard AMD require()/define() protocol, AMD is not really helping you with these modules. Unless you plan to write your own modules using define(), then you could use just about any async loader.
That said, there is a way to make curl.js work with non-AMD modules/files. Use the js! plugin. Here's your first block of files translated to use the js! plugin (note I also added the ".js" ext back on which I like to do with non-modules):
// we load the core files first, then get the next block that depends on them
curl([
"js!MooTools/Core/mootools-1.2.2-core-jm.js",
"js!jQuery/Core/jquery-1.3.2.js"
]).next([
"js!MooTools/mGeneral.js",
"js!jQuery/Core/jquery.tools.min.js",
"js!jQuery/ThirdPartyPlugIns/jquery.tmpl.js"
]).then(onSuccess, onError);
If any of those files within each array depend on each other, you can also use the !order suffix on them to ensure they wait for other files before executing/evaluating (be sure you're setting proper cache headers, though). Actually, the !order suffix is the fastest method as long as there are no caching issues (mobile browsers add some additional constraints on file size).
Were there any other error messages? Specifically, I would expect curl.js to throw at least one error besides just "Promise not completed".
Also, please check the Net tab (Firebug) or the Network tab (Chrome) to check that curl.js is looking in the correct location for the modules.
FWIW, I am planning to remove the alias require --> curl. The reason is that the global require function is non-standard (and explicitly not standardized in the AMD proposal). I suggest you use curl() instead of require().
curl.js also allows it's top-level api to be aliased explicitly via the "apiName" config param if you really, really want to use the name "require". :)
<script>curl = { apiName: "require" }; </script>
<script src="path/to/curl.js"></script>
<script>require(["some/modules"]).then(success, failure);</script>
More FWIW: the standard require is typically only needed in a module and can be requested by including it as a dependency:
define(["require"], function (require) {
require(["another/module"], function (another) {
// use another module here
});
});
-- John
If you're only doing normal javascript file loading (not modules), as it appears, i would encourage you to check out LABjs (http://labjs.com). LABjs focuses on being the most performance optimized loading solution (to the exclusion of some other features like module/dependency style stuff).
In fact, LABjs 2.0a (https://github.com/getify/LABjs/blob/master/next/LAB.src.js), which will be fully released in the next few days, is really exceptionally fast (even more than 1.2) at loading general scripts in parallel. I encourage you to give it a try, unless (as John eludes to above) you plan to go to module syntax... then stick with Curl or RequireJS.
Is anyone familiar with Yabble or other browser-side CommonJS loaders?
I'm experimenting with Node.js and would very much like to create Javascript modules which can be used interchangeably on the server side and the client side. This may end up being more a "because it's awesome" kind of thing more so than "because it's practical and useful" kind of thing.
As such, I'm basically trying to get the CommonJS require() method to work on the browser-side, which is exactly what Yabble is supposed to do. I don't really know where to start with it though. I can't seem to find any documentation other than what's found in Yabble's Github readme, and that's not helping much.
Essentially all I've done is put this in an HTML page...
<script src="yabble.js"></script>
<!-- Uses require -->
<script>
require.setModuleRoot('http://localhost:8030/')
my_module = require('my_module')
</script>
But anytime I call the require() function all I get a Synchronous require() is not supported. exception thrown.
Can someone help me get started? Where am I supposed to load yabble.js where am I supposed to call require? Is there a special way to run my Javascript modules?
When loading Javascript code that will need to use the require() function into the browser, the entry point into that code must be the require.run() function.
e.g., Good:
<script src="yabble.js"></script>
<script>
require.setModuleRoot('http://localhost:8030/')
require.run('my_module') // <-- Uses require() function somewhere
</script>
e.g., Bad (Will get the Synchronous require() is not supported error):
<script src="yabble.js"></script>
<script src="http://localhost:8030/my_module.js"></script> <!-- <== Use's require function somewhere -->
FYI, it's pretty nifty how Yabble does this. It will actually statically analyze your Javascript source code, I think basically just using a regular expression to look for the require() method, and then try to pull that .js script from the server, then it does the same static analysis of that .js script, and on and on.
This can be particularly confusing because it will actually load those .js scripts even if the control logic would mean program flow would never reach the require() function. e.g., if you had...
if (False) { require('some_module'); }
... Yabble will still load this module.
Synchronous loading of modules in the browser is problematic. A construct like:
var x = require('something_remote.js')
Implies that the browser will halt your code (i.e. block), go and fetch the remote file, parse it, and then return to you the exports. But this does not jive with the single-threaded browser environment - we would be halting the main JavaScript thread (and thus page interactivity for the user) on the performance of the network. So browsers have evolved against this scenario, to favor async loading on their own schedule. There is some good discussion here:
http://www.sitepen.com/blog/2010/07/16/asynchronous-commonjs-modules-for-the-browser-and-introducing-transporter/
One pattern which might work here is that a require() implementation does synchronously block, fetches the file via XHR and then evals it, but that seems to run against all the browser support/infrastructure for async file-based loading. Also I'm curious what implications that would have for the cross-domain primitive of browser security.
So in order to fit the browser async loading model, we'll need to use a callback mechanism like:
require("something.js", function () { // called later, after something.js has loaded! })
It looks like RequireJS is doing this:
http://requirejs.org/docs/start.html
Perhaps give that a shot?
JavaScript environments like NodeJS etc - built with the provision of loading "local" modules from disk, instead of foreign network hosts - can do the synchronous load.
I would greatly appreciate any corrections from JS experts :-)