Is it possible to override the global require function, affecting it at process level?
From what I know, the require function is provided as argument in the function that wraps the NodeJS scripts:
(function (..., require, __dirname) { // something like this
// The wrapped code
})(...);
Is there any way to modify the require function?
(function () {
var _require = require;
require = function () {
console.log("...");
_require.apply(this, arguments);
};
})();
This will probably affect only the script where it's located.
How can we modify it at the process level?
var Module = require('module');
var originalRequire = Module.prototype.require;
Module.prototype.require = function(){
//do your thing here
return originalRequire.apply(this, arguments);
};
mock-require does this by overriding Module._load (which is what the real require actually calls).
Here is a much safer native ES6 answer based on #orourkedd which acts like an event listener on all require calls, It might look like its replacing require but if you look closer its actually saying: require = require and trap calls to it but return original behaviour. This is just one of the millions of uses of Proxy() which has been really handy for me, for example in Typescript for mapping tsconfig "paths" with the real module node will resolve.
I would go as far as to say that this is not "Monkey patching" as its on a lower level of the language.
var Module = require('module');
Module.prototype.require = new Proxy(Module.prototype.require,{
apply(target, thisArg, argumentsList){
let name = argumentsList[0];
/*do stuff to ANY module here*/
if(/MyModule/g.test(name)){
/*do stuff to MY module*/
name = "resolveAnotherName"
}
return Reflect.apply(target, thisArg, argumentsList)
}
})
This is the workaround I found. If there is any better solution, I'm open to see it.
I created a script named req-modifier.js:
module.exports = function (_args) {
var _require = _args[1];
function newRequire () {
console.log("Require is called");
return _require.apply(this, arguments);
}
newRequire.__proto__ = _require;
_args[1] = newRequire;
};
Then from the files I want to modify the require function, I do:
require("./req-modifier")(arguments);
var foo = require("./foo");
The limitation is that I have to call every time the req-modifier function.
Related
I found 2 ways to define a global object using IIFE, like these:
(function () {
var func = function () { };
window.func = func;
}());
vs:
(function (myFunc) {
window.func = myFunc();
}(function () {
var func = function () { };
return func;
}));
I notice that almost js famous plugins use the second way, ex: jquery:
Why's that?
I think it's clearly a visual matter. UMD code may support multiple module patterns.
The second approach separates the UMD code from the module code. By opening the corresponding module file, one can see at the top, in one place, which module patterns are supported.
I am using what I understand to be the Javascript module pattern, and jQuery.
I have an app which has a public and an admin side. Each has its own JS file, though some functionality is shared so I have extracted it to a common file. Gulp combines the common + public files into a single file for use on the public side, and the common + admin files into a single file for use on the admin side.
The public JS file includes something like:
var PublicFoo = (function () {
var bar = function() {
// ..
};
var init = function() {
$button.on('click', Common.someCommonThing);
};
return {
init: init
};
})();
The HTML page where this code is needed fires it off like so:
<script>
PublicFoo.init();
</script>
The admin JS file includes something very similar, also defining a bar() function, and calling the same Common module function.
var AdminFoo = (function () {
var bar = function() {
// ..
};
var init = function() {
$button.on('click', Common.someCommonThing);
};
return {
init: init
};
})();
The common JS file (shared and combined with both public and admin JS) includes something like:
var Common = (function () {
var someCommonThing = function() {
// Do stuff.
// When done, I want to call bar() in the calling module.
// This does not work, throws 'Uncaught ReferenceError: bar is not defined'
bar();
};
return {
someCommonThing: someCommonThing,
// ...
};
})();
From the Common module, how can I reference a function in the calling module?
I know about .caller, but apparently that is non-standard and should not be used.
I could maybe somehow pass in the name of the calling module as a parameter to Common, and reference it, but that seems ugly:
// In PublicFoo
var init = function() {
$button.on('click', function() {
Common.someCommonThing(PublicFoo)
});
};
// In Common
var someCommonThing = function(callingModule) {
// ...
callingModule.bar();
I could also of course extract the bar() call out and do it back in the calling module, but that doesn't seem so neat either:
// In PublicFoo
var init = function() {
$button.on('click', function() {
Common.someCommonThing();
bar();
});
};
// ... and the same thing in AdminFoo
I feel like this must be JS modules 101, a basic requirement, and yet I can't seem to find anything about it, though I may be searching using the wrong terminology. Or is the reason I can't find how to do this because it should not be done this way?
How can I reference the appropriate bar() from the Common module?
I know about .caller, but apparently that is non-standard and should not be used.
Also it doesn't work in your case, as the caller is the event handler and neither PublicFoo nor AdminFoo.
I could maybe somehow pass in the name of the calling module as a parameter to Common, and reference it
Yes, passing references to the thing that you want to be called is the way to go if you want someCommonThing to do different things after it has finished. Notice you really should only use such a callback when the thing is asynchronous, otherwise just returning and calling bar afterwards (like in your last snippet) is much easier.
How can I reference the appropriate bar() from the Common module?
If both bars might be loaded at once into the page, then there's no way around a parameter that references the callback.
However, that doesn't seem to be the case in your example - on one page, AdminFoo takes the role of Foo and on the other page PublicFoo takes the role of Foo.
So just reference only Foo.bar from Common! Let the respective pages fill it with the appropriate value, i.e.
var Foo = AdminFoo
on the admin page and
var Foo = PublicFoo
on the public page.
Passing functions to other functions is very common and perfectly idiomatic JavaScript, so you could do it like this:
// In PublicFoo
var bar = function() {
// ..
};
var init = function() {
$button.on('click', function() {
Common.someCommonThing(bar)
});
};
// In Common
var someCommonThing = function(bar) {
// ...
bar();
};
I try to work with RequireJS and AMD module definition and have write a module that do my things in object format i think.
(i went from jquery and have not study a OOP javascript well)
myModule.js
define([
jquery,
datepicker,
], function ($, datepicker) {
var myModule = {
debug: true,
lang: 'auto',
initModule: function (element) {
myModule.element = element;
},
// ... other methods
}
return myModule;
});
And it work well, but if i try to use it for more than one elements/time it override him self, and i can't use it more than one time in same page.
main.js
requirejs(['MyModule'],
function (MyModule) {
// all the elements on page
$elements = $('.element');
$elements.each(function () {
MyModule.initModule($(this));
});
});
When i have more than one <div class="element"> on page only the last one work, i think because my module is override him self.
I tried to add new MyModule() but have a error TypeError: MyModule is not a constructor
I think i need to add a constructor or something else, in any case have a instance of my module to use instead of the object (that i think are precompiled by requirejs and returned ready for work). Any helps are good, many thanks in advance!
Ok! For do that! I completely refactor my code, and instead of return a object in my module definition i prototyped a function for get after his instance and i create a constructor for reset the properties/vars:
myModule.js
define([
jquery,
datepicker,
], function ($, datepicker) {
// constructor
var myModule = function () {
// reset lang because it maybe was changed in previous instance,
// i think because javascript share this thing trough objects?
myModule.prototype.lang = 'auto';
}
myModule.prototype.debug = true
myModule.prototype.lang = 'auto';
myModule.prototype.initModule = function (element) {
myModule.element = element;
};
// ... other methods with `myModule.prototype.` prefix
return myModule;
});
Great, now i can call myModule trough new myModuel() syntax and have same functionality for different elements on page.
main.js
requirejs(['MyModule'],
function (MyModule) {
// all the elements on page
$elements = $('.element');
var p = 1, _mod = [];
$elements.each(function () {
_mod[p] = new MyModule();
_mod[p].initModule($(this));
p++;
});
});
This work for me, i not completely understand yet what i do, but my purpose are satisfated, i can reuse same module functionality for different elemnts on page.
Suggest me readings:?
I securely need to read something about OOP Javascript, prototype and how javascript manage instance/class/object/var in memory and namespaces.
normally we might create a simple singleton object like so with Node.js:
var foo = {};
module.exports = foo;
or
function Foo(){}
module.exports = new Foo();
however
what is the best way to make a clean singleton module that needs an external variable for initialization? I end up making something like this:
var value = null;
function init(val){
if(value === null){
value = val;
}
return value;
}
module.exports = init;
this way someone using the module can pass in an initializing value for a certain variable. Another way to do it would be like so:
function Baz(value){
this.value = value;
}
var instance = null;
module.exports = function init(value){
if(instance === null){
instance = new Baz(value);
}
return instance;
}
there's two problems I encounter with this:
(1) this is minor, but the semantics is wrong. We can rename init to getInstance, but we can't make the same function literal mean "initialize and get" since they are different meanings. So we have to have a function that does two different things. Create an instance and retrieve and instance. I don't like this especially since in some cases we need to make sure the argument to initialize the instance is not null. With multiple developers using a module it's not clear if a module has been initialized yet, and if they pass in undefined into the module that hasn't been initialized, that could become a problem or just confusing at the least.
(2) this is more important - in some cases initializing Baz is asynchronous. For example, making a Redis connection or reading from a file to initialize a singleton, or making a socket.io connection. This is what really trips me up.
e.g. here is a module that I have that I consider really ugly that stores a socket.io connection:
var io = null;
var init = function ($io) {
if (io === null) {
io = $io;
io.on('connection', function (socket) {
socket.on('disconnect', function () {
});
});
}
return io;
};
module.exports = {
getSocketIOConn: init
};
the above module is initialized like so:
var server = http.createServer(app);
var io = socketio.listen(server);
require('../controllers/socketio.js').getSocketIOConn(io);
So I am looking for a design pattern that allows us to create a singleton module where the initialization process is asynchronous. Ideally we won't have the same function both initializing the instance as well as retrieving it. Does such a thing exist?
I don't think there is necessarily a way to create a pattern that solves this problem but perhaps I am making the mistake of structuring my code in a way that is creating a problem that doesn't need to exist- the problem of initializing a module with a value only once, but using one function to both init the instance and retrieve the instance.
It sounds like you're trying to create a module that gets initialized in one place and then uses some shared resource from that initialization for other users of that module. That is a semi-common need in the real world.
First off, it's ideal if a module can load or create the things that it depends on because that makes it more modular and useful on its own and puts less of a burden on someone using it. So, in your case, if your module could just create/load the thing that it needs when the module is first created and just store that resource in it's own module variable, then that would be the ideal case. But, that is not always possible because the shared resource may be someone else's responsibility to set up and initialize and this module just needs to be made aware of that.
So, the common way to do that is to just use a constructor function for the module. In Javascript, you can allow the constructor to take an optional argument that provides the initialization info. The code responsible for setting up the module would call the constructor with the desired setup parameter. Other users of the module that weren't responsible for setting up the module could just either not call the constructor or if they want a return value or there are other constructor parameters that they should pass, they could pass null for that setup parameter.
For example, you could do this:
var io;
module.exports = function(setup_io) {
if (setup_io) {
io = setup_io;
}
return module.exports;
};
module.exports.method1 = function() {
if (!io) {
throw new Error("Can't use method1 until io is properly initalized");
}
// code here for method1
};
// other methods here
Then, users of the module could either do this:
// load myModule and initialize it with a shared variable
var myModule = require('myModule')(io);
or this:
// load myModule without initializing it
// (assume some other module will initialize it properly)
var myModule = require('myModule');
Note: For developer sanity, it would be useful to have individual methods that require appropriate setup (before they can be used properly) to check to see if the module has been setup when any method is called that needs that setup in order to properly inform a developer that they have called a method before setting up the module properly. Otherwise, errors can happen much further downstream and likely won't have useful error messages.
If you now want the initialization process to be async, that can be done too, but it certainly complicates other uses of the module because they won't necessarily know when/if the module has been initialized.
var moduleData;
var readyList = new EventEmitter();
module.exports = function(arg, callback) {
// do some async operation here involving arg
// when that operation completes, you stored the result
// in local module data and call the callback
readyList.on("ready", callback);
someAsyncOperation(arg, function() {
// set moduleData here
// notify everyone else that the module is now ready
readyList.emit("ready");
// remove all listeners since this is a one-shot event
readyList.removeAllListeners("ready");
});
return module.exports;
};
If you have other users of this module that wish to be notified when it has finished initializing, you can allow them to register a callback themselves to be notified when the module is ready.
// pass a callback to this method that will be called
// async when the module is ready
module.exports.ready = function(fn) {
// if module already ready, then schedule the callback immediately
if (moduleData) {
setImmediate(fn);
} else {
readyList.on("ready", fn);
}
};
If, for reasons I don't quite understand, you want to use the same constructor for both initialization and ready detection, that can be done, though I don't think it's near as clear as just using a separate method for ready detection:
var moduleData;
var readyList = new EventEmitter();
module.exports = function(arg, callback) {
// if both arguments passed, assume this is a request for module
// initialization
if (arguments.length === 2) {
// do some async operation here involving arg
// when that operation completes, you stored the result
// in local module data and call the callback
readyList.on("ready", callback);
someAsyncOperation(arg, function() {
// set moduleData here
// notify everyone else that the module is now ready
readyList.emit("ready");
// remove all listeners since this is a one-shot event
readyList.removeAllListeners("ready");
});
} else {
// constructor called just for a ready request
// arg is the callback
if (moduleData) {
// if module already ready, then schedule the callback immediately
setImmediate(arg);
} else {
// otherwise, save the callback
readyList.on("ready", arg);
}
}
return module.exports;
};
Usage for async initializing the module:
// async initialization form
var myModule = require("myModule")(someArg, function() {
// can use myModule here
});
Usage for loading the module and getting notified when someone else has initialized it:
var myModule = require("myModule")(function() {
// can use myModule here
});
I see a lot of code here, here:
var module = (function (module) {
module.prototype.something_else = function () {
};
return module;
})(module);
Why var module = part present at all? And why return module; if previous part is not needed?
I see usage of:
var module = (function(module) {...})(module || {});
for cases when module wasn't already defined sometimes... Is that above case?
This block of code is only used if module is already defined and you want to extend it (e.g., add a new method):
var module = (function (module) {
module.prototype.something_else = function () {
};
return module;
})(module);
It accepts module as an input parameter and returns the extended module. The assignment of var module = then replaces the original module.
Answering your questions one by one:
Why var module = part present at all?
In the example above (taken from your first URL), var module = is not necessary. The simple example they provide is silly. You could accomplish the exact same thing with this:
module.prototype.something_else = function () {};
Using the above pattern to extend a class makes more sense with the examples provided in your second URL ( http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html ):
var MODULE = (function (my) {
var old_moduleMethod = my.moduleMethod;
my.moduleMethod = function () {
// method override, has access to old through old_moduleMethod...
};
return my;
}(MODULE));
Immediate executing function creates a new scope where we can preserve the old method var old_moduleMethod = my.moduleMethod;
Next question:
And why return module; if previous part is not needed?
You need return module because otherwise the function wouldn't return anything and the var module = assignment would be set to an undefined value.
Next question:
for cases when module wasn't already defined sometimes... Is that above case?
Yes, that is the case. If module isn't defined then you would need to pass in an empty object. However, you typically would use a pattern to extend an object if it isn't defined in the first place. That would make no sense and would just complicate your code.
To understand, it helps to rename identifiers to get the equivalent
var module = (function (module_impl) {
module_impl.prototype.something_else = function () {
};
return module_impl;
})(module || {});
module_impl is the object that is to hold the module's public API. So after populating it, the anonymous function returns it to the caller, which assigns it to the global module. This way the API is now available using module while any implementation details are hidden in the closure created by the anonymous function.
module || {} now is to allow augmentation: the first time it gets called, module is still undefined since the assignment to the return value of the anonymous function has not happened yet. Thus `module || {} evaluates to the second operand.
To further illustrate why the assignment is needed. The first time, the stub gets called, it is effectively the same as
var module = (function () {
var module_impl = {};
// ...
return module_impl;
})());