monkeypatch exported function - javascript

running on nodev4 -
let's say that I have 2 libraries : foo and bar
foo has this
var bar = require('./lib/bar');
exports = module.exports = function myApp(options) {
[snip]
}
exports bar = bar;
and bar has this
module.exports = function doStuff(moreOptions) {
function doMoreStuff () {
}
}
my app has
x = requires(foo);
what I would like to do is get my app to monkeypatch the doMoreStuff function - is this possible ?
I have tried various libraries , but I suspect there's a fundamental problem with my understanding of js ;)

Lets look at what you have here. After
x = requires(foo);
you have the following essentially
x = function (options){ /* function work */ }
x.bar = function(moreOptions){
function doMoreStuff(){
}
}
This, while not 'illegal' it is odd. It's the equivalent of
a = function() { return "I'm a function"; }
a.bar = "I'm a string attached to a function";
console.log(a()); // => "I'm a function"
console.log(a.bar); // => "I'm a string attached to a function"
Your bar module doesn't do much. It's a function containing an inaccessible function. Lets assume you meant
module.exports = function(moreOptions){
return {
doMoreStuff: function(){
return "Bar doing more stuff";
}
}
}
If you want to new up an myApp and attach an external function you would
function myApp(options){
}
myApp.prototype.bar = bar(); // since you exported a function
module.exports = myApp;
In your main app you could now
x = require('foo');
var app = new foo(); // you MUST otherwise you get an empty function
app.bar.doMoreStuff(); // => "Bar doing more stuff"
Alternatively (and less prone to error) foo could be
var bar = require('bar');
module.exports = function (options) {
// work here ...
return {
bar: bar(), // again, exported as function
appOptions: options,
// ...
}
}
Then in the main module
x = require('foo');
x.bar.doMoreStuff(); // => "Bar doing more stuff";
Hope this helps.

Related

Exporting a function in NodeJS, different attempts returned different errors: undefined, TypeError properties undefined, and promise pending [duplicate]

I was wondering what the best approach is for configuring a module export. "async.function" in the example below could be a FS or HTTP request, simplified for the sake of the example:
Here's example code (asynmodule.js):
var foo = "bar"
async.function(function(response) {
foo = "foobar";
// module.exports = foo; // having the export here breaks the app: foo is always undefined.
});
// having the export here results in working code, but without the variable being set.
module.exports = foo;
How can I export the module only once the async callback has been executed?
edit
a quick note on my actual use-case: I'm writing a module to configure nconf (https://github.com/flatiron/nconf) in an fs.exists() callback (i.e. it will parse a config file and set up nconf).
Your export can't work because it is outside the function while the foodeclaration is inside. But if you put the export inside, when you use your module you can't be sure the export was defined.
The best way to work with an ansync system is to use callback. You need to export a callback assignation method to get the callback, and call it on the async execution.
Example:
var foo, callback;
async.function(function(response) {
foo = "foobar";
if( typeof callback == 'function' ){
callback(foo);
}
});
module.exports = function(cb){
if(typeof foo != 'undefined'){
cb(foo); // If foo is already define, I don't wait.
} else {
callback = cb;
}
}
Here async.function is just a placeholder to symbolise an async call.
In main
var fooMod = require('./foo.js');
fooMod(function(foo){
//Here code using foo;
});
Multiple callback way
If your module need to be called more than once you need to manage an array of callback:
var foo, callbackList = [];
async.function(function(response) {
foo = "foobar";
// You can use all other form of array walk.
for(var i = 0; i < callbackList.length; i++){
callbackList[i](foo)
}
});
module.exports = function(cb){
if(typeof foo != 'undefined'){
cb(foo); // If foo is already define, I don't wait.
} else {
callback.push(cb);
}
}
Here async.function is just a placeholder to symbolise an async call.
In main
var fooMod = require('./foo.js');
fooMod(function(foo){
//Here code using foo;
});
Promise way
You can also use Promise to solve that. This method support multiple call by the design of the Promise:
var foo, callback;
module.exports = new Promise(function(resolve, reject){
async.function(function(response) {
foo = "foobar"
resolve(foo);
});
});
Here async.function is just a placeholder to symbolise an async call.
In main
var fooMod = require('./foo.js').then(function(foo){
//Here code using foo;
});
See Promise documentation
An ES7 approach would be an immediatly invoked async function in module.exports :
module.exports = (async function(){
//some async initiallizers
//e.g. await the db module that has the same structure like this
var db = await require("./db");
var foo = "bar";
//resolve the export promise
return {
foo
};
})()
This can be required with await later:
(async function(){
var foo = await require("./theuppercode");
console.log(foo);
})();
ES6 answer using promises:
const asyncFunc = () => {
return new Promise((resolve, reject) => {
// Where someAsyncFunction takes a callback, i.e. api call
someAsyncFunction(data => {
resolve(data)
})
})
}
export default asyncFunc
...
import asyncFunc from './asyncFunc'
asyncFunc().then(data => { console.log(data) })
Or you could return the Promise itself directly:
const p = new Promise(...)
export default p
...
import p from './asyncModule'
p.then(...)
Another approach would be wrapping the variable inside an object.
var Wrapper = function(){
this.foo = "bar";
this.init();
};
Wrapper.prototype.init = function(){
var wrapper = this;
async.function(function(response) {
wrapper.foo = "foobar";
});
}
module.exports = new Wrapper();
If the initializer has error, at least you still get the uninitialized value instead of hanging callback.
You can also make use of Promises:
some-async-module.js
module.exports = new Promise((resolve, reject) => {
setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000);
});
main.js
var asyncModule = require('./some-async-module');
asyncModule.then(promisedResult => console.log(promisedResult));
// outputs 'someValueToBeReturned' after 2 seconds
The same can happen in a different module and will also resolve as expected:
in-some-other-module.js
var asyncModule = require('./some-async-module');
asyncModule.then(promisedResult => console.log(promisedResult));
// also outputs 'someValueToBeReturned' after 2 seconds
Note that the promise object is created once then it's cached by node. Each require('./some-async-module') will return the same object instance (promise instance in this case).
Other answers seemed to be partial answers and didn't work for me. This seems to be somewhat complete:
some-module.js
var Wrapper = function(){
this.callbacks = [];
this.foo = null;
this.init();
};
Wrapper.prototype.init = function(){
var wrapper = this;
async.function(function(response) {
wrapper.foo = "foobar";
this.callbacks.forEach(function(callback){
callback(null, wrapper.foo);
});
});
}
Wrapper.prototype.get = function(cb) {
if(typeof cb !== 'function') {
return this.connection; // this could be null so probably just throw
}
if(this.foo) {
return cb(null, this.foo);
}
this.callbacks.push(cb);
}
module.exports = new Wrapper();
main.js
var wrapper = require('./some-module');
wrapper.get(function(foo){
// foo will always be defined
});
main2.js
var wrapper = require('./some-module');
wrapper.get(function(foo){
// foo will always be defined in another script
});

function.prototype not working properly with module.exports

I have a file that includes the current function
function foo(){
/*Some members*/
}
foo.prototype.func = function(p1){
/*some logic*/
return this
}
module.exports = foo
and in the test file
let x = require('First file path');
x.func(p1) /*Throws an error that it's not defined*/
x.prototype.func(p1)/* works normally */
/*I also tried*/
let obj = x();
I am trying to make an npm package and it's not practical to type the prototype every time how to solve this?
Your foo.js should be
function foo() {
/*Some members*/
}
foo.prototype.func = function (p1) {
/*some logic*/
console.log(p1);
}
module.exports = foo;
and usage file should be:
var foo = require('./foo');
var instance = new foo(); //<---notice here
console.log(instance.func("hello"));

Differences in javascript module pattern

Very simple question, not sure if there are any differences in these ways of creating a javascript "module". I'm hoping somebody can clarify it for me.
A)
var foo = function() {
var bar = function() {
console.log('test');
};
return {
bar: bar
};
};
B)
var foo = function() {
function bar() {
console.log('test');
};
return {
bar: bar
};
};
C)
var foo = function() {
this.bar = function() {
console.log('test');
};
return {
bar: this.bar
};
};
A and B are essentially the same, though there is a very minor difference between A and B due to function/variable hoisting, theoretically you could write code which would work in B but break in A, but practically speaking you'd have to really write weird code to do so.
C will work, but is conceptually wrong. The point of using this.funcName in a function is as a constructor (creating lots of objects using new Thing(). If you aren't using the function as a constructor you shouldn't be using that style as someone scanning the code may mistake the function as a constructor instead of its actual purpose which is a module.
At first, you forgot to execute the function expression: the module pattern is an IEFE. You just create a function.
Your last example is nonsense, it looks like a constructor function when assigning properties to this - and when executed as a IEFE it breaks (and using it with new has undesired effects; an when returning an object it's useless).
For the difference between the first and the second snippet see var functionName = function() {} vs function functionName() {}. In context of the module pattern, the function declaration is recommended.
//Javascript Module Pattern
var person = (function() {
var cname = 'CheapFlight';
return {
name: "Santosh Thakur",
getAge: function() {
return cname;
},
growOlder: function() {
return cname + " Updated";
}
};
}());
person.cname = "New Company"
console.log(person.cname);
console.log(person.name);
console.log(person.getAge());
console.log(person.growOlder());
prefix var before a function makes it a "class"-ish, this means you can make many versions of it. This goes for A
For example:
var hi = function()
{
var bye = function()
{
alert("bye");
}
bye(); // this will call bye
var something = new bye(); // this will create a new instance of bye();
}
var something = new hi();
something();
B means you can only call bar, not make a new instance of it inside the function.
C is the same as bar because of its scope
Class-ish:
var Dog = function( hair, type )
{
this.hair = hair;
this.type = type;
}
var fred = new Dog( "long", "Dalmation" );
alert( fred.hair );
var dave = new Dog( "short", "Poodle" );
alert( dave.type);
This is a class ^

JavaScript design patterns: Injecting a dependency that is not yet created

I have a CommonJS module:
// main-module
module.exports = function () {
var foo,
someModule = require('other-module')(foo);
// A value is given to foo after other-module has been initialised
foo = "bar";
}
As you can see, this requires other-module:
// other-module.js
module.exports = function (foo) {
function example() {
console.log(foo);
// > "bar"
}
}
I would like the example function inside of other-module to be aware of the foo variable inside of main-module, even though is it established after the module is required.
When other-module runs, foo will not be undefined. However, the point is that by time my example function runs, foo will have been given a value of bar.
The pattern above obviously does not work. What design pattern do I need to implement?
I'm not super-familiar with CommonJS, so this might not be the idiomatic way to do it, but using a function instead of a variable should work:
// main-module
module.exports = function () {
var foo,
someModule = require('other-module')(function() { return foo; });
foo = "bar";
}
// other-module.js
module.exports = function (fooFn) {
function example() {
console.log(fooFn());
}
}
The foo value (a string) will be passed by value, so it's undefined inside other-module. You could use an options object that is passed by reference:
var options = {},
someModule = require('other-module')(options);
options.foo = "bar";

How to get 'this' value of caller function?

If I have a function like this:
function foo(_this) {
console.log(_this);
}
function bar() {}
bar.prototype.func = function() {
foo(this);
}
var test = new bar();
test.func();
then the test instance of bar gets logged.
However, for this to work I have to pass the this in the bar.prototype.func function. I was wondering whether it is possible to obtain the same this value without passing this.
I tried using arguments.callee.caller, but this returns the prototype function itself and not the this value inside the prototype function.
Is it possible to log the test instance of bar by only calling foo() in the prototype function?
If the question is 'without passing this (by any means)' then answer is no
value can be passed by alternative methods though. For example using global var (within Bar class) or session or cookies.
function bar() {
var myThis;
function foo() {
console.log(myThis);
}
bar.prototype.func = function() {
myThis = this;
foo();
}
}
var test = new bar();
test.func();
I think calling foo within the context of bar should work:
function foo() {
console.log(this.testVal);
}
function bar() { this.testVal = 'From bar with love'; }
bar.prototype.func = function() {
foo.call(this);
}
var test = new bar();
test.func(); //=> 'From bar with love'
You can do this without changing the external function, but you must change the way you call it.
You can't get the context of the caller, but you can set the this property on a function you call with the method apply or call. See this reference for an explanation on this.
function foo()
{
console.log( this );
}
function bar()
{
bar.prototype.func = function func()
{
foo.apply( this );
};
}
var test = new bar();
test.func();
Usually if this is used, it's in an object oriented context. Trying to call a method of an object with another this might indicate poor design. Explain a bit more what you are trying to achieve for more applicable design patterns.
For an example of a javascript OOP paradigm, check my answer here.
What about this?
"use strict";
var o = {
foo : function() {
console.log(this);
}
}
function bar() {}
bar.prototype = o;
bar.prototype.constructor = bar;
bar.prototype.func = function() {
this.foo();
}
var test = new bar();
test.func();
Or this:
"use strict";
Function.prototype.extender = function( o ){
if(typeof o == 'object'){
this.prototype = o;
}else if ( typeof o == 'function' ) {
this.prototype = Object.create(o.prototype);
}else{
throw Error('Error while extending '+this.name);
}
this.prototype.constructor = this;
}
var o = {
foo : function() {
console.log(this);
}
}
function bar() {}
bar.extender(o);
bar.prototype.func = function() {
this.foo();
}
var test = new bar();
test.func();

Categories