This question already has answers here:
In Node.js, how do I "include" functions from my other files?
(28 answers)
Closed 5 years ago.
Suppose I have a module, named mainModule.js, that has the statement.
var helper_formatModule = require('/formatModule.js');
Inside formatModule.js, I also have a statement,
var helper_handleSentences = require('/handleSentences.js');
If my original module, mainModule.js, needs functions defined in the handleSentences.js module would it be able to access them? I.e if it imported formatModule, a module that has handleSentences, does it have access to those? Or would I need to import the handleSentences.js module directly?
Only requiring a module A somewhere (in module B, for example) doesn't make the functions of A accessible in other modules. Normally, they're not even accessible in module B.
To access functions (or any values) from another module, that other module has to export them. The following scenario will not work:
// module-a.js
function firstFunction () {}
function secondFunction () {}
// module-b.js
var helper_handleSentences = require('/handleSentences.js');
// do something with 'helper_handleSentences'
module.exports = function (a) {
return helper_handleSentences(a);
}
As you can see, module-a.js doesn't export anything. Thus, the variable a holds the default export value, which is an empty object.
In your situation, you can either
1. require both modules in mainModule.js
// handleSentences.js
function doSomethingSecret () {
// this function can only be accessed in 'handleSentences.js'
}
function handleSentences () {
// this function can be accessed in any module that requires this module
doSomethingSecret();
}
module.exports = handleSentences;
// formatModule.js
var helper_handleSentences = require('/handleSentences.js');
// do something with 'helper_handleSentences'
module.exports = function (a) {
return helper_handleSentences(a);
};
// mainModule.js
var helper_handleSentences = require('/handleSentences.js');
var helper_formatModule = require('/formatModule.js');
// do something with 'helper_handleSentences' and 'helper_formatModule'
2. merge the exported values of both modules into one object
// handleSentences.js
function doSomethingSecret () {
// this function can only be accessed in 'handleSentences.js'
}
function handleSentences () {
// this function can be accessed in any module that requires this module
doSomethingSecret();
}
module.exports = handleSentences;
// formatModule.js
var helper_handleSentences = require('/handleSentences.js');
// do something with 'helper_handleSentences'
function formatModule (a) {
return helper_handleSentences(a);
};
module.exports = {
handleSentences: helper_handleSentences,
format: formatModule
};
// mainModule.js
var helper_formatModule = require('/formatModule.js');
// use both functions as methods
helper_formatModule.handleSentences();
helper_formatModule.format('...');
Related
When calling a function in the module in this way
app.get("/api/sessions/oauth/google", (req, res) => {
return google_callback.googleOAuthHandler(req, res);
});
this points to the module and another function in the module can be accessed using this
googleOAuthHandler : async function (req, res) {
const code = req.query.code.toString();
const {id_token, access_token} = await this.getGoogleOAuthToken(code);
}
However passing the function as a parameter changes this to global and this.getGoogleOAuthToken becomes undefined
i.e when doing
app.get("/api/sessions/oauth/google", google_callback.googleOAuthHandler);
how would i access getGoogleOAuthToken in googleOAuthHandler in google_callback module when using this way
app.get("/api/sessions/oauth/google", google_callback.googleOAuthHandler);
When passing function this way this doesn't mean the module. So this.getGoogleOAuthToken doesn't work.
however we can use module.exports.getGoogleOAuthToken to access the function within the same module. Using module.exports.getGoogleOAuthToken also works in the first example.
Alternatively if you don't like module.exports to call the function you can place line const _this = this; at the top of the file or const _this = module.exports = { ... } and use _this.function to call a function inside the module.
Also just noticed that in the first example this.function only works because i'm using this syntax.
module.exports = {
func1 : function(){},
func2 : function(){}
}
when exporting with
module.exports.func1 = function(){}
module.exports.func2 = function(){}
this cannot be used to access the other function
Referencing this solution, I need to pass a parameter into module.exports of my utils.js file.
// utils.js
var module;
module.exports = function (name) {
if (module) return module;
module = {};
module.sayHi = function () {
return `Hi, ${name}`;
};
return module;
};
I'm a bit confused as to how to call sayHi after requireing utils.js.
// index.js
const utils = require("./utils")("Jim");
utils.sayHi();
I'm getting TypeError: utils.sayHi is not a function. What's the right way to call sayHi?
First you create a variable named module.
var module;
This does nothing because you are doing this in the scope of the module, so that variable already exists.
Then you assign a function to module.exports.
In another module, you import that function and call it.
The first line of that function says:
if (module) return module;
Is module a truthy value?
Yes. It is an object. If it wasn't, then assigning to module.exports would have throw an exception.
Consequently, you never overwrite module = {}; or assign the sayHi function to it.
Now look at the answer you referenced:
module.exports = function (app, db) {
var module = {};
It creates a new variable in the scope of the function so it doesn't conflict with the existing one.
I am writing a module that needs to call internal functions within the module and make use of variables in the constructor. To call these functions internally I could either use the variable mycode or use the keyword this. However using mycode means using a global variable and this can be overwritten by parts of my functions. This is a simplified model of my module's structure:
// app.js
const MyCode = require('mycode.js');
var mycode = new MyCode();
mycode.function1($(html));
// mycode.js
module.exports = class {
constructor() {
this.alertUrl = true;
}
function1(html) {
html.find('a').each(function () {
var url = $(this).attr('href');
this.function2(url); // this is now overridden by jquery
});
}
function2(url) { if (this.alertUrl) alert(url); }
}
I am looking for a solution that would work like myModule.function2(url);, where myModule is only available to functions inside the module.
You can use an arrow function instead, so that the this reference is inherited from the outer scope, rather than being altered by the each callback:
html.find('a').each((_, elm) => {
var url = $(elm).attr('href');
this.function2(url);
});
Another (less elegant) option is to save a reference to the instance before calling the each:
function1(html) {
var self = this;
html.find('a').each(function () {
var url = $(this).attr('href');
self.function2(url);
});
}
The problem doesn't really have anything to do with modules, just the calling context of functions.
you can use async function with export like this...
const function_name = async () => {
};
export default function_name ;
I'm trying to unit test a function in a file while stubbing another function in the SAME file, but the mock is not being applied and the real method is being called. Here's an example:
// file: 'foo.js'
export function a() {
// .....
}
export function b() {
let stuff = a(); // call a
// ...do stuff
}
And my test:
import * as actions from 'foo';
const aStub = sinon.stub(actions, 'a').returns('mocked return');
actions.b(); // b() is executed, which calls a() instead of the expected aStub()
Some restructuring can make this work.
I've used commonJS syntax. Should work in the same way in ES6 as well.
foo.js
const factory = {
a,
b,
}
function a() {
return 2;
}
function b() {
return factory.a();
}
module.exports = factory;
test.js
const ser = require('./foo');
const sinon = require('sinon');
const aStub = sinon.stub(ser, 'a').returns('mocked return');
console.log(ser.b());
console.log(aStub.callCount);
Output
mocked return
1
While the above does work, it's definitely a workaround as my linter was quick to inform.
I ended up separating modules and using proxyquire. This library allows you to easily substitute any / all exports with those of your choosing, sinon stub spy or mocks included. e.g. :
in b.js
export const fnB = () => 'hey there!';
in a.js
import { fbB } from 'b.js';
export const fnA = () => fbB();
in a.test.js
import { noCallThru } from 'proxyquire';
const proxyquireStrict = noCallThru();
const stubB = stub().returns('forced result');
const moduleA = proxyquireStrict('a.js', {
'b.js' : { fnB: stubB }
}).fnA;
console.log(fnA()); // 'forced result'
The method mentioned above (using a factory to collect the functions) works well; however, eslint will not like the use of a variable/function that has not yet been declared. Therefore I would recommend a slight modification:
// my-functions.js
export const factory = {};
export const funcA = () => {
return facory.funcB();
};
factory.funcA = funcA;
export const funcB = () => true;
factory.funcB = funcB;
// my-functions-test.js
import {factory, funcA, funcB} from './path/to/my-functions';
describe('MyFunctions | funcA', () => {
test('returns result from funcB call', () => {
const funcBStub = sinon.stub(factory, 'funcB').returns(false);
// Test that the function does not throw errors
let result;
expect(() => (result = funcA())).not.toThrow();
// Test that the return value is that of the mock rather than the original function
expect(result).toEqual(false);
// Test that the stub was called
expect(funcBStub.called).toEqual(true);
});
});
// Don't forget to test funcB independently ;)
The important distinction is to add the functions within the file to the factory as they are defined to avoid break eslint rules. The only case where this could cause issues is if you tried calling one of those functions within the same file before they have all been defined. Example:
// my-functions-1.js
export const factory = {};
export const funcA = () => {
factory.funcB();
};
factory.funcA = funcA;
// Since the code execution runs from top to bottom, calling funcA here means that funcB has not yet been added to factory
funcA(); // Throws an error since factory.funcB() is not a function (yet)
export const funcB = () => true;
factory.funcB = funcB;
I prefer this technique of using a "collector" to call functions within the same file since it is not always a great idea to create separate files for EACH function that you write. Often, I find that I will create many related utility functions in order to make my code more readable, reusable, and composable; putting each function into a separate file would make the code slightly more difficult to understand since a reader could not see the definitions of these functions without bouncing between different files.
I met with the same issue and found one method. You can change your foo.js file to this:
// file: 'foo.js'
export function a() {
// .....
}
export function b() {
let stuff = exports.a(); // using "exports." to call a
// ...do stuff
}
Please refer to https://codeburst.io/stub-dependencies-with-sinon-js-259ac12379b9.
Can we reuse var name without overwriting its details in JavaScript.Taking below example of augmented module pattern
<script>
var Module = (function () {
// Module object
var module = {},
privateVariable = "Hello World";
function privateMethod() {
// ...
}
module.publicProperty = "Foobar";
module.publicMethod = function () {
//console.log( privateVariable );
return privateVariable;
};
return module;
})();
//Defining same name MODULE var again
var Module = (function (my) {
var newvar = 999;
my.anotherMethod = function () {
return newvar;
};
return my;
}(Module));
alert(Module.publicMethod());
//How this upper MODULE property is accessible ? Should be hide by
//next same name MODULE var?**
alert(Module.anotherMethod());
</script>
Above code is running perfectly fine and adding one more anotherMethod under MODULE but how it is still accessing initial module property. Defining var with same name (MODULE) shoudn't overwrite (remove) the upper module.
Defining var with same name (MODULE) shoudn't overwrite (remove) the upper module.
Yes, it should.
The global scope (or the function if you are inside a function) is scanned for var statements. Since you have two identical ones, the second one is ignored. MODULE is created in the global scope.
Then you run a function and then assign its return value to the MODULE.
Then you run another function, passing the current value of MODULE as an argument to it, then you assign the return value to MODULE.
A reference to the object created at var my = {} still exists in the scope of the second function, but the only reference to it from the global scope has been overwritten.