The problem is that I have a number of separate modules which I export using module.exports and are inter dependent. Say-
mongohelper
transaction
server
conhandlr
appmin
Now, the server module contains a common object that is required by the other four modules. However, when compiling the node app, some of these modules are compiled before the server module for example by using console output I found that the order was -
Compile order-
mongohelper
transaction
server (..the upper modules have undefined common object now)
conhandlr
appmin
So, is there a way by which I can make sure that the server module compiles first so that any dependent modules dont have undefined objects?
Without any actual code, it's hard to understand what you really want to know, but I'll try to give you a basic understanding of how node modules work.
require("module") is a synchronous call. The complete module is evaluated/"compiled" before the parser goes on with the next line of code. This means, that all dependencies are executed in the order they were specified. They are also only executed once per process. That means, that if you're requiring the same module multiple times, it is only executed at the first time and its module.exports is cached.
I suggest reading the docs.
Related
I have a self contained JavaScript function in one file, and some Mocha BDD tests in another file that reference it using [nodejs] require(). So in my function under test I export using module.exports. That's all well and good, in the IDE/build.
Now my function under test is actually an external virtual endpoint, which when deployed into a cloud instance, runs standalone inside a JSVM sandbox (Otto) which has no support for exports or modules, and is ES5 based (it does however embed a version of the Underscore library). If I leave the nodejs module definition in there when I deploy to cloud, it kicks off an error at runtime (as Otto doesn't recognise modules). So I want to remove it, and use some vanilla JS mechanism for the linkage back to the Mocha tests and test runner.
So my question is, if I can't use nodejs or requirejs modules, how can I link my Mocha tests in one file to a JS function in another? I had a play with placing a function closure (which most module implementations use) in the file under test, and Otto is happy with this, as its vanilla JS, but any variable with global scope in the file is still not visible from my test file, so there is no linkage.
Any thoughts?
From a quick look at the Otto docs, it looks like Otto only wants whole files and (as you've said) doesn't recogise commonjs modules from node.
If you've got many files I would recommend bundling them into a single file with webpack/browserify/etc, which is how most people convert modules for use in the browser, which similarily doesn't recognise commonjs modules without tooling.
Alternatively, you could convert all the module.exports to simple var declarations, concatenate the files together and hope you don't have a naming collision.
I don't see anything in the docs about having access to a window or global object to hang globals onto, which limits your options
One of my colleague came up with a suggestion to use closure in the file under test which gets deployed into the cloud instance, if you are running under Nodejs, and conditionally do the export. I added the small anonymous closure below to do this, and Otto doesn't complain.
(function () {
if (typeof module != 'undefined') {
module.exports = pdp_virtual_endpoint;
}
}());
Not sure why I didn't think about this earlier :)
This is a problem I faced more than one. Here is an example file structure:
app.js
folder
-- index.js
-- module1.js
-- module2.js
From app.js, the entry point of my application, I require folder/index.js. This file itself is just a loader who requires all the other files in the directory. module1.js and module2.js both define some methods I want to use eventually. They are never directly required by app.js since index.js takes care of that and adds common helper utilities and applies some transformations to these modules.
All works well if I then use some methods defined in those files from app.js after I required them. But the problem comes when a method defined in module2.js wants to use a method defined in method1.js (or vice-versa). Sometimes it will work, sometimes not (in folders with multiple files I didn't get to find out when precisely it works and when it doesn't yet).
If, from module2.js I require ./index.js and then use methods in it defined by module1.js, I sometimes get Cannot read property 'myMethod' of undefined. I assume it has to do with the order the modules are required by index.js, but I can't seem to find a solution to this common problem (other than duplicating code or not using methods of these other modules).
Is there a common solution to this problem? I tried doing something like this :
var modules = require(./index.js);
exports.myMethod = function() {
if(!modules.module1 || !modules.module1.myOtherMethod) {
modules = require('./index.js');
}
modules.module1.myOtherMethod();
};
But it doesn't to do anything, modules.module1 is still undefined.
It just sounds like module should require module2. That's the solution to module1 needing to call methods in module2.
If you're worried about many calls to require, don't. That's standard practice in every programming language I've used (in particular look at the import statements in any Java program. Java is verbose, I know, but this is correct practice.)
It's definitely bad practice to look at code in one module and have no idea where anything comes from, because the require statements are missing.
You have a circular dependency problem. Try moving some of the common functions to a third file and have module1 and module2 require it, or make sure that one of them requires the other in one way only.
Never ever require a file that requires the current file back.
Module loader is responsible for loading modules.
What I know is module loader loads modules in browser asynchronously whereas in Node.js it loads synchronously.
I wanted to confirm whether this information is correct or not.
ES6 module loaders will be asynchronous while node.js module loaders are not.
Here are some key aspects of module loaders:
Module code automatically runs in strict mode and there’s no way to opt-out of strict mode.
Variables created in the top level of a module are not automatically added to the shared global scope. They exist only within
the top-level scope of the module.
The value of this in the top level of a module is undefined. Does not allow HTML-style comments within the code (a leftover feature from
the early browser days).
Modules must export anything that should be available to code outside of the module.
https://leanpub.com/understandinges6/read#leanpub-auto-modules
Modules, in general, solve several problems for developers. First,
they allow the developer to separate code into smaller pieces, called
modules. Second, they make it easy for developers to load (inject)
those modules into other sections of code. Having modules injected
like this helps keep project code uncoupled from the module (read:
improved testability). And third, modules can load scripts
asynchronously. This means that apps can begin loading faster, as
they don’t require all scripts to be loaded prior to executing code.
http://chimera.labs.oreilly.com/books/1234000001623/ch03.html#_default_values
On the other hand because node.js is based on require which is synchronous this means node.js does not provide an asynchronous variant out of the box.
Of course there are async module loaders for node (async-require), but natively (with require) is not supported.
ESM is intentionally async (to accomodate loading over networks) and the rationale behind import also aims at knowing during code interpretation what dependencies exist (e.g. allowing bundlers to do treeshaking etc). This is also the reason to have imports at the beginning of your files and they can't be conditional (unless you use the await import() syntax).
You can also not eval(readFileSync(moduleFile)) if you use ESM syntax in the loaded file.
I tried to add some custom functions into the FS module of NodeJS, this module is part of NodeJS' core programs. I found the corresponding file (fs.js) in the following location: /usr/lib/nodejs. The problem was that the changes that I've made seemed to not affect anything when the corresponding module and function was called.
What I did was I added a function like this in /usr/lib/nodejs/fs.js:
fs.someRandomFunc = function(){return 'Yeah!'}
However, when I called the function, it replied :
var fs = require('fs')
console.log(fs.someRandomFunc())
// Error Message
TypeError: Object #<Object> has no method 'someRandomFunc'
By the way, this also happens to the other core modules, such as module.js and path.js. Does this happen because NodeJS caches the core JS program instead of loading it from /usr/lib/nodejs?
Any idea to resolve this issue would be appreciated.
Thanks!
fs is part of NodeJS' Core Modules. As such, it is compiled into binary and distributed. So modifying the source is not going to take effect unless you recompile them.
It is anyway not a good idea to modify Node's source files directly. What you can/should instead is extend the existing fs module with your own functions, like graceful-fs does, or replace it entirely with your version, like fs-extra does.
Im using requireJS to dynamically load JS modules in my html5 single page web application. Im just wanting to know whether I should dispose of the requireJS loaded modules once i have finished with them (so the garbage collector can clean them up)? And if so than how do you dispose a required module from requireJS?
Thanks in advance
It is possible to undefine a module:
There is a global function, requirejs.undef(), that allows undefining
a module. It will reset the loader's internal state to forget about
the previous definition of the module. However, it will not remove the
module from other modules that are already defined and got a handle on
that module as a dependency when they executed. So it is really only
useful to use in error situations when no other modules have gotten a
handle on a module value, or as part of any future module loading that
may use that module. See the errback section for an example. If you
want to do more sophisticated dependency graph analysis for undefining
work, the semi-private onResourceLoad API may be helpful.
http://requirejs.org/docs/api.html#undef
I'm not too sure on the internals but in my usage of the lib I've not found it necessary to do any manual clean up of modules.