I know this questions sounds like a duplicate of this question but it isn't.
This questions shows how to include a file that then stores all of its members in an own namespace. But is there a way to include the file, so that the members are in the default namespace?
So I want something like this,
include("abc.js");
testFunc(1, 2, 3);
where testFunc is declared in abc.js
There is a common namespace in node.js that all loaded files has access to, global
In abc.js:
global.testFunc = () => 'bar';
so below will work
require('./abc');
testFunc(1, 2, 3);
However this is not really advised to be used for performance purposes, except for config values for example
First nodejs does not know include, you should use require or import
If you have a module (testModule):
module.exports = {
testFunc: (...args) => {/* ... */}
}
You should be able to import testFunc into the current 'namespace' using
const {testFunc} = require("./testModule.js");
Related
I'm studying module pattern and have a question.
I want to use 'settings' anywhere.
script1.js
var MODULE = (function() {
var t = {};
this.settings = { // this == Window
users: ['john', 'emma']
}
return t;
})()
script2.js
MODULE.dom = function() {
var t = this; // this == MODULE
document.querySelector('p').textContent = t.settings.users[0]; // error
function _say() {
return t.settings.users[1] // error
}
return {
say: _say
}
}
MODULE.DOM = MODULE.dom.call(MODULE)
When use this.settings = {...}, 'this' means Window so code doesn't work.
When use t.settings = {...}, 'this' means MODULE so code works but when write MODULE in dev console, settings is exposed in MODULE variable. Is it ok?
I'd greatly appreciate any help, thank you!
When use t.settings = {...}, 'this' means MODULE so code works
That's the right way to do it.
but when write MODULE in dev console, settings is exposed in MODULE variable. Is it ok?
It's mostly OK.
If you're worried about the client being able to type in the variable name and see the code that gets run - there's no way to avoid that. They can just look at the devtools to see what the network requests are, and what is downloaded - or look at the Sources panel.
If you're worried about running into naming collisions with larger scripts, then - sometimes, libraries deliberately assign themselves to the window to allow other parts of the code to access them. Perhaps you'd like your MODULE to be like this. If not, then you should utilize JavaScript modules instead, which allow for scripts to be imported inside other scripts without polluting the global namespace at all or having any possibility of naming collisions. For example, you could do
// script1.js
export const MODULE = {
settings: {
users: ['john', 'emma'];
}
};
// script2.js
import { MODULE } from './script1.js';
// proceed to use MODULE
And you can do import { MODULE } from './script1.js'; from any script file, not just script2.js.
Personally, I consider the IIFE module pattern in JavaScript to be mostly obsolete nowadays. For any reasonable-sized script, better to write code in separate files and then import and export as needed. (A 1000 line file is somewhat hard to debug and refactor. Ten 100 line files are easier to debug and refactor.)
I found questions related to this but not exactly what I was looking for. I am wondering if this is possible to do something along the lines of, if you mock a internal dependency (like a module/file you created) / external deps, can you ignore all imports in that file by default and only allow the ones you need?
Example, pretend the method foo is being tested, and its inside a file called Foo.js, I only need the camelCase depedency to work as normal cause its used inside the foo function, but the rest of the dependencies, can be mocked to avoid loading something i wish to not load (like some code thats just living in the file not in a class or method)
// Foo.js
const { get } = require('lodash');
const camelCase = require('camelcase');
const Bar = require('../../../Bar.js');
...
const foo = () => {
// need to test this method and only needs camelcase
...
}
Is this possible to say "ignore every dependency, except this one if my test function requires (imports) the Foo.js file in order to test the foo function?
I am very new to Jest so Sorry if my question my not make perfect sense or maybe something simple, or a better solution. I am working with an existing code base and some includes get really deep with more and more imports more down the tree and I can only really work with whats in the test functions
thanks in advance!
I have a Node.js module that I have kept as a single file up to this point. It's getting rather large though and has a lot of functionality in it that might be better separated into other modules. For example, separating out logging initialization and functionality into it's own module.
My module has a lot of (I want to say "global" but not really) top-level variables that lots of different functions access, use and modify. If I separate out functionality into separate files/modules and require them into my primary module, what is the proper approach to passing those variables between the modules?
For example, with everything in one module/file, it's easy to do this:
const logger = (log, message) {........}
const makeRequestHandler = (url, filepath) {
....
logger.info('some message here')
....
}
So it's pretty easy to access top-level systems like the logger. But, if I decided to split my logger and makeRequestHandler into their own modules/files, how would I handle this?
let logger = require('./mylogger') // Custom module
let makeRequest = require('./makerequest') // Another custom module
makeRequest.handler(url, filepath, logger)
This would work, but it doesn't seem elegant or optimal. It would get even more weird if I have a lot of different variables that I needed to pass in:
makeRequest.handler(url, filepath, logger, profiler, reportingBuffer, compressionHandler)
I've also considered passing stuff into the modules when requiring:
let makeRequest = require('./makeRequest')(logger)
or better yet:
let makeRequest = require('./makeRequest')(this) // I can access all variables made in my primary/top-level module
Is there an approach here that is more proper and better/easier to maintain? Is the last one the best approach?
What about a global locator pattern or service locator/service provider pattern as pointed out in comments wherein you can have something like a service registry and include these services in any module you want to use them in.
Although I am not sure about being the best solution of all, but it is easier to implement and feels like a neater solution than passing in the this context around the modules.
//logger.js
const logger = (log, message) {........}
export logger
Now, in the app file is where you can initialize the logger and other service instances and register them in the global locator
let logger = require('./mylogger') // Custom module
init() {
//init and set the logger
global.logger = new logger();
...
}
And this is how you can use it in the code to makRequest
let logger = global.logger;
const makeRequestHandler = (url, filepath) {
....
logger.info('some message here')
....
}
What I feel is problem with these solutions :
//Solution 1 : As you pointed out yourself this can get messy when number of paramters increase and is not very readable or understandable.
let logger = require('./mylogger')
let makeRequest = require('./makerequest')
makeRequest.handler(url, filepath, logger)
//Solution 2 : Passing around the `this` context is never a good idea,for keeping sensitive data independent or scope isolation
let makeRequest = require('./makeRequest')(this)
note :
This article explains some aspects of this solution in detail for your consideration.
Also there are some npm modules which provide these features like Service Locator
. HTH
I'm converting an existing codebase from js/react/jsx setup to TypeScript. Naturally, I'd like to do it file by file, and have a question about approaches for making TS compiler work with the existing js codebase.
I convert file index.js but want to leave foo.js in JavaScript for now:
// index.ts
import { fooFunction } from 'foo';
foo({ val: 1 });
// foo.js
export const fooFunction = ({ val, optionalProp }) => {
//...
}
The problem in this example that TypeScript automatically infers argument to foo and complains that Property 'optionalProp' is missing in type { val:string, optionalProp:any }
Needing to "stub" the type of fooFunction sent me looking and I found a few ways i may be able to do it:
1) Use require instead of import
// index.ts
var fooFunction: any = require('foo').fooFunction;
2) Merge declarations
?
3) Add a d.ts file with custom declarations for foo - haven't attempted but seems inconvenient
Ideally I don't have to do (1) because I want to keep using import syntax and I don't have to do (3) because that will require me to add declaration files only to remove them later when I'm ready to convert foo.
(2) sounds awesome, but I can't figure out a working solution.
// index.ts
declare module 'foo' {
function fooFunction(options: any): any
}
Doesn't work and throws Cannot redeclare block-scoped variable 'fooFunction'
How do I do that? Are there docs that have examples of what I'm trying to do and/or have more explanation about declaration merging and how to work with namespace/interface/value?
Are there better approaches for incrementally transitioning to TypeScript?
This may not work, just wanted to preface this with that - I don't know much at all about React - but I know for sure that you can use ? on a variable to make it "optional". I've used this before in functions
myFooFunction(requiredParam: typeA, optionalParam?: typeB) { ... }
Another thing you should consider is the fact that Typescript can add some type checking at compile time, so IMO you should leverage that as much as possible.
Edit: to work with the optional parameter, you could just check that it exists.
myFooFunction(requiredParam: typeA, optionalParam?: typeB) {
if (optionalParam) { // if this results to true, the param was given
//do something
}
}
I have two files: server.js and db.js
server.js looks as such:
...
const app = express();
app.use('/db', db());
app.listen(3000, () => {
console.log('Server started on port 3000')
});
...
and db.js as such:
...
function init() {
const db = require('express-pouchdb')(PouchDB, {
mode: 'minimumForPouchDB'
});
return db;
}
...
This works just fine, and I am able to reach the pouchdb http-api from my frontend. But before, I had const PouchDBExpress = require('pouchdb-express'); in the top of db.js, and the first line in init() looked like this; const db = PouchDBExpress(PouchDB, {. This gave an error in one of the internal files in pouchdb saying cannot set property query on req which only has getters (paraphrasing).
So this made me copy the exaples from pouchdb-servers GitHub examples which requires and invokes pouched-express directly, and everthing worked fine. Is there an explanation for this? I'm glad it works now, but I'm sort of confused as to what could cause this.
The only difference between:
require('module')()
and
const mod = require('module');
mod();
is that in the second case, you retain a reference to the module exports object (perhaps for other uses) whereas in the first one you do not.
Both cases load the module and then call the exported object as a function. But, if the module export has other properties or other methods that you need access to then, obviously, you need to retain a reference to it as in the second option.
For us to comment in more detail about the code scenario that you said did not work, you will have to show us that exact code scenario. Describing what is different in words rather than showing the actual code makes it too hard to follow and impossible to spot anything else you may have inadvertently done wrong to cause your problem.
In require('module')(), you don't retain a reference of the module imported.
While in const mod = require('module'); mod(), you retain a reference and can use the same reference later in your code.
This problem might be due to some other reason like -
Are you using a some another global instance of the db, and your code works in the given case as you are making a local instance
Some other code dependent scenario.
Please provide more details for the same