perhaps I have not worded the title correctly. Below is the explanation of what I'm trying to do.
I'm creating a helper.js file for my project. Inside it contains many functions, one I've pasted below. I export this function using module.exports.
function generateInternalError(message, stack_trace) {
if (process.env.NODE_ENV == 'dev') {
console.log({ message: message, stack_trace: stack_trace });
} else {
console.log({message: message});
}
}
module.exports = {
generateInternalError: generateInternalError
};
Where I want to utilize this function I would call:
helper.generateInternalError('Not Found',new Error().stack);
And it works as expected.
But, what I have been tasked with, is creating categories of functions. Essentially I need the following:
helper.errors.generateInternalError('Not Found',new Error().stack);
I can not seem to figure out the right way to export a class of functions or an object of functions in NodeJS such that I don't get an error like:
TypeError: helper.errors.generateClientError is not a function
Any assistance is appreciated.
Thank you
The module.exports property of a file is simply an object that maps names to functions. You can define it arbitrarily, for example:
module.exports = {
errors: {
generateInternalError,
...
},
...
};
Then, require('./helper').errors.generateInternalError will be defined.
helpers is just noise if everything is a helper, so drop that. Just use regular modules and unless you are sure you only have one function in that category export multiple functions. If you only export one function with module.exports then you don't need to do that as a property of an object which also means you can just say const genError=require('./errors')
Don't make something like helpers.errors.someErrorFunc because helpers is noise and you make categories with just separate module files. Don't try to make Node.js look like Java or something equally horrible.
It might be better to structure your helper sub classes in separate files.
Example
src/helpers.js
src/helpers/
src/helpers/errors.js
File helpers.js
module.exports = {
errors: require('./helpers/errors')
}
File helpers/errors.js
module.exports = {
generateInternalError: function(){
//write some internal error code here
}
};
Structuring your code like this will keep your root helpers file very organized and create a pattern that is easy to replicate for new subclasses.
If you prefer a less modular approach you could simply just return one big JSON object as other's have demonstrated...
module.exports = {
errors: {
generateInternalError: function(){
//internal error code
},
generateDatabaseError: function(){
//db error code
}
}
}
Related
I have a file containing the definition of a Object and in that same file I have a function that is part of this object like so:
export function ARScene(_callbacks) {
this.callbacksObject = _callbacks;
// more fancy code..
}
ARScene.prototype.changeCar = function() {
//some fancy code here
this.loadHDCar(); // THIS LIKE GENERATES A ERROR.
}
now I have a different file containing an other method that is part of the Object called ARScene like so:
import { ARScene } from './arScene';
ARScene.prototype.loadHDCar = function() {
//some more fancy code..
}
What is happening when I build this with webpack and run it in the browser I get the error that this.loadHDCar(); is undefined I guess this happens because webpack doesnt add a file if it is not imported. But how do I make sure that ARScene.prototype.loadHDCar is added to the object in the final output?
I am a complete newbie to webpack and modules. I have found answers on stackoverflow about this but they had slightly different scenarios then me. So their solutions didnt work (or maybe I didnt understand it).
If more context or information is needed please let me know.
How do I make sure that ARScene.prototype.loadHDCar is added to the object in the final output?
You should import it in the arScene module, and you should even create the prototype method in there (where you are defining the class) for visibility.
export function loadHDCar() {
… //some more fancy code
}
import { loadHDCar } from './loadHDCar';
export function ARScene(_callbacks) {
…
}
ARScene.prototype.loadHDCar = loadHDCar;
ARScene.prototype.changeCar = function() {
… // some fancy code here
this.loadHDCar();
};
I'm moving my nodejs project from Javascript to Typescript. It's going to be a slow process, slowly changing things over a few months as i need to tweak stuff.
I've created a typescript class that looks something like this:
// RedisRepository.ts
export class RedisRepository {
public async getDevice(serial: string) : Promise<Device> {
// blah
return device;
}
}
Then in another Javascript file where i need to reference and then call the functions on the above class.
// ExpressApi.js
const repository = require('../Redis/RedisRepository');
async function getRedis(req, res) {
try {
const device = await repository.getDevice('serialnumberxxx');
res.status(200).end(JSON.stringify(device ));
} catch (e) {
logger.error(e);
res.status(500).end();
}
}
however, when it tried to call the function on the repository it says it doesn't exist. Using chrome debugger, i can see that it exists at: repository.RedisRepository.prototype.getDevice. This doesn't seem the correct way to use the function though.
While I appreciate I could just convert ExpressApi.js to Typescript. I'm going to have this problem with many different files. So i need to use it as JavaScript for now. I'll slowly continue to go round the project and change things to Typescript.
As #crashmstr mentioned, you should create a new instance of RedisRepository, then call getDevice method.
If you still want to use
const repository = require('../Redis/RedisRepository');
syntax, you could export default new RedisRepository() from your RedisRepository.ts file.
I have a problem with implementing Singleton pattern in my project, which runs on NodeJS (version 8 as far as I know). I created a Logger class, which I want to use whenever we want to log something to a console or database. Originally I implemented this as a Class like this:
class Logger {
constructor() {
}
log() {
}
logToDatabase() {
}
}
module.exports = new Logger()
And I was able to call const logger = require('./Logger') from other classes and use logger.log() function. I then did some research and found a post on StackOverflow where someone recommended to implement the module like this:
module.exports = {
log: () => {
},
logToDatabase: () => {
}
}
So I changed my code and everything (almost) is still working fine. I encountered the problem when I wanted to call logger.log() from another .js file (within their module.exports functions), like so:
another_file.js
const logger = require('./Logger')
module.exports = {
foo: () => {
logger.log()
}
}
The error was logger.log() is not a function.
I managed to solve it by doing something like this:
var logger
module.exports = {
init: () => {
logger = require('./Logger')
},
foo: () => {
logger.log()
}
}
And I made sure that I call init function before I do any calls to foo in my main index.js file.
This seems to work fine now and I don't get any errors, but I want to make sure that I'm doing it the valid way, not by using some cheap hack that shouldn't work but appears to be fine. I would also like to understand why I encounter this issue (I imagine this may be caused by my lack of understanding how module.exports or require actually works. Am I right thinking this can be caused by using different modules? I got a "warning" in code saying we're using CommonJS, and it can be converted to ES6. I've heard about Babel which allows you to convert a code from one module to another (if I understand correctly), although this project ends in a week time and I would want to avoid using new things as much as possible.
Thanks for any help!
I am new to grunt... I just tried to implement a custom task (using TypeScript) that shall iterate over a set of given files and do some processing. This is what I have so far...
function gruntFile(grunt: IGrunt): void {
grunt.registerMultiTask("custom", "...", () => {
this.files.forEach(function(next) {
...
});
});
var config: grunt.config.IProjectConfig = {
custom: {
files: [
"folder1/*.json",
"folder2/**/*.json"
]
}
};
grunt.initConfig(config);
}
(module).exports = gruntFile;
Currently I struggle with the configuration and how I can acccess the files array in my custom task handler function. Grunt gives me the error that it cannot read the property forEach of undefined. I also tried a configuration that looks like that...
var config = {
custom: {
files : [
{ src: "folder1/*.json" },
{ src: "folder2/**/*.json" }
]
}
};
Not sure about that, but I have seen that in some tutorials...
I have seen a couple of sample grunt-files already, but in each example the configuration looks a bit different, or files are used in conjunction with imported tasks and modules, so the samples do not show how the configured files are accessed. Any guidance that helps me to better understand how it works (and what I am doing wrong) is appreciated.
Update
I found out that I can query options via the config-property, but I am not sure if this is the right way to do it. In my task-handler I do this to query the list of configured files...
var files = grunt.config.get("custom.files");
...which returns the expected array (but I find it a bit odd to query options via a path expression). I realized that (by using TypeScript) the scope of this is not the context of the current task; that is the reason why files was always undefined. Changing the call to registerMutliTask to...
grunt.registerMultiTask("custom", "...", function() { ... });
...fixed this problem. I use wildcard characters in the path-expression; I was hoping that Grunt can expand those expressions and give me a list of all matching paths. Does this functionality exist, or do I have to create that on my own?
I was able to iterate over the configured files (file pattern) by using the following code...
grunt.registerMultiTask("custom", "...", function() {
grunt.file
.expand(this.data)
.forEach(function(file) {
...
});
});
I am trying to build a set of utils for my NodeJS project. These helpers will include: text utils (like substringing, console logging etc.), and more specific helpers like parsing the text of a tweet.
So I am trying to divide the module in different files and with a very clear idea of what each thing is meant to do.
For example I would like to achieve this:
var helpers = require("helpers");
var Utils = new helpers.Utils();
// working with text
Utils.text.cleanText("blahblalh");
// working with a tweet
Utils.twitter.parseTweet(tweet);
As you can see I am using Utils for different things, by calling very specific methods and sub methods.
I tried to understand how inheritance works here but I got a little bit lost.
This is what I am doing (some rough sample code):
//node_modules/helpers/index.js
var Text = require('./text');
var Twitter = require('./twitter');
function Utils() {
}
Utils.prototype.text = {
cleanText: function(text) {
Text.cleanText(text);
}
};
Utils.prototype.twitter = {
parseTweet(tweet) {
Twitter.parseTweet(tweet);
}
};
//node_modules/helpers/text.js
function Text() {
}
Text.prototype.cleanText = function(text) {
if (typeof text !== 'undefined') {
return text.replace(/(\r\n|\n|\r)/gm,"");
}
return null;
};
module.exports = Text;
//node_modules/helpers/twitter.js
function Twitter() {
};
Twitter.prototype.parseTweet = function(data) {
return data;
};
module.exports = Twitter
Is this a correct way? Am I doing something wrong or that could slow down the performances, etc?
To clarify how I'm understanding your post, I see two questions:
How do I structure code/methods within files, files that represent a category of utility functions
How do I organize the those categorical files into one larger library
Structuring methods within a category
Rather than making all of the category specific functions methods of objects (e.g. Twitter or Text), you could just export the functions in files named after them. Since it seems you are passing in the data you want to use, there is no need to make the functions instance methods of some empty class.
If your usage patterns of Twitter or Text usually have class variables you want to keep state on, and you want to instantiate Text or Twitter objects to use your examples, then I suppose that would be appropriate. When I setup util libs in my projects it usually is a bunch of exported functions that make up a module, rather than an exported javascript class.
To provide an example of what a text.js file made up of text-based utility functions might look like:
module.exports = {
cleanText:function(text) {
// clean it and return
},
isWithinRange(text, min, max) {
// check if text is between min and max length
}
}
Alternatively, you could do it this way:
exports.cleanText = function(text) {
// clean it and return
}
exports.isWithinRange = function (text, min, max) {
// check if text is between min and max length
}
Structuring utility category files to make a larger utility library
As far as organizing the utility methods, Luca's example is nice. I've organized some similarly like this:
utils-module/
lib/
text.js <-- this is the example file shown above
twitter.js
test/
index.js
Where index.js does something like
var textUtils = require('./lib/text');
exports.Text = textUtils;
Then when I want to use the util lib in say some User model in my node API, it's simply:
/*
* Dependencies
*/
var textUtils = require('path/to/lib').Text;
/*
* Model
*/
function User() {}
/*
* Instance Methods
*/
User.prototype.setBio = function(data) {
this.bio = textUtils.cleanText(data);
}
module.exports = User;
When I was first learning it was very helpful to look at popular, well-respected libraries to see how more experienced node/javascript devs were doing things. There are so many good (and bad) ones out there!
You can see a utils library example with lodash.
Lodash is an utility lib like underscorejs.
This library have file sustem structure like your.
It divides the functions in categories. Each category is a folder with an index.js file that includes into a namespace (literal object) each functions for that category!
Lodash/
Objects/
Function1.js
Functions2.js
....
Index.js
Array/
Function1.js
...
Index.js
Then in your code you can do this:
var objectsUtils = require("lodash/objects");
var foreach = require("lodash/array/each");
You can create a similar file system structure in order to have more flexibility.
You can require the entire lib, only one namespace or a single function.
This is better for performance, because you use only what you need and have a memory usage gain.