JS modules: How implement sort of an interface? - javascript

I'm working with JS modules bundled with Webpack.
Suppose I have a common module, used everywhere. This module require another module, let's say it is an output for errors
var err = require("./errors.js");
var common = {
doSomething: function() {
var a = 1;
if (a == 1) {
err.output('An error occured');
}
}
}
module.exports = common;
Now this error management module could be somthing like
var $ = require("jquery");
var errors = {
output: function(msg) {
$('<div class="someClass">'+msg+'</div>).appendTo('body');
}
}
module.exports = errors;
And finally I have my entry point:
var common = require("./common.js");
common.doSomething();
My question is: since I have got two applications, let's call them backend and frontend, I would like different implementation of errors.output, because it's view-bounded. Maybe in backend I want to use a class different from "someClass", or maybe I don't want to use a DIV, but a P, or else.
I have multi entry points, actually. So I wouldn't like to have each of them passing around lots of callbacks or configuration. I would like to have only one implementation of errors module for all the entry point of the backend and only one for all the entry point of the frontend, without any code repetition.
This is something that I would implement with interface, in PHP.
Which is the best approach for Javascript?
Thank you

Related

Using AMD/Require modules with Aurelia

We're looking into updating our Durandal app to Aurelia (finally). Our biggest concern right now is code re-use. We'll write TypeScript for the view logic, but there's a lot of complex clientside media access (webRTC stuff) that has taken a lot of time to get working as raw JavaScript AMD modules.
I've seen questions asked about using AMD ViewModels; I'm asking about using AMD modules within new aurelia viewmodels.
As a simple example, I have a mediaDeviceScanner.js module:
define(["modules/logger"], function (logger) {
'use strict';
const mediaDeviceScanner = {};
mediaDeviceScanner.scanDevices = function() {
return navigator.mediaDevices.getUserMedia({video:true}).then(function(stream) {
return stream;
}).then(function(stream) {
return navigator.mediaDevices.enumerateDevices().then(function (availableDevices) {
const mediaDevices = [];
for (let i = 0; i < availableDevices.length; ++i) {
const deviceCandidate = availableDevices[i];
if ((deviceCandidate.kind === "videoinput") && deviceCandidate.deviceId != "default" && deviceCandidate.deviceId != "communications") {
mediaDevices.push({ label: deviceCandidate.label, kind: (deviceCandidate.kind == "videoinput" ? "Camera " : "Microphone ") + (mediaDevices.length + 1), id: deviceCandidate.deviceId });
}
}
return mediaDevices;
}).catch(function (error) {
logger.log(error, logger.logLevels.warning, logger.features.webcam, logger.features.webcam);
});
})
}
return mediaDeviceScanner;
});
What's the happy-path to calling mediaDeviceScanner.scanDevices from within an aurelia viewmodel?
In my Durandal vm, I have this:
define(["amd/mediaDevices/mediaDeviceScanner"],function(mediaDeviceScanner){
mediaDeviceScanner.scanDevices().then(function(devices){alert('woot')});
});
I'd like to get a gauge on what kind of "reuse costs" there will be before I evaluate "framework shift" costs.
There is an old question regarding this topic. Using AMD module as an Aurelia ViewModel
It essentially boils down to which loader you are using. Aurelia CLI by default uses requirejs but recently got an update to support SystemJS. With that it would be possible to, as described in the referenced question, create wrappers for your existing code. The wrappers could be very thin and maybe even generalized to save lots of boilerplate
--EDIT--
Out of interest I've just quickly tried it with a new CLI Project, based on SystemJS.
After scaffolding I've placed your example module in scripts/amd/media-device-scanner.js
Removed the logger dependency, since its not provided in your example
Go to src/app.js and inside the constructor add this code:
System.import('../scripts/amd/media-device-scanner.js').then((result) => {
result.scanDevices();
}
Still works like a charm ;)

NodeJS Group Functions Under A Sub-Class

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
}
}
}

Combining Angular Services with NodeJS Modules

Supposing I have a library written in Javascript to be used in a MEAN stack application.
I wish to use my library both from NodeJS and within Angular.
To remain idiomatic I would like the library to appear as a Module inside node and as a Service within Angular.
the only way I can think to do this is to do something like:
var myLibrary = function(){
var myLib = {};
myLib.myFunc1 = function() {
//Do some cool stuff
};
return myLib;
};
if (typeof module !== 'undefined') {
module.exports = myLibrary();
} else{
var app = angular.module('myApp.services', []);
app.factory('myLibrary',myLibrary);
}
This will work, but it has at least two significant limitations:
The namespace is polluted with the variable "myLibrary"
If within the library I want to use other node modules or Angular services then I can't
I would like to know if anyone knows of a better solution, or if I should give up on using Angular services and use one of the libraries that allows client side Node module functionality.
Having done a bit of searching about this looks like the best solution:
https://gist.github.com/sevcsik/9207267

Best way to structure helpers functions in NodeJS

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.

How to organize models in a node.js website?

I have just started experimenting with building a website using node.js, and I am encountering an issue when organizing the models of my project.
All the real world examples I have found on the Internet are using Mongoose. This library allows you to define your models in a static way. So you can write this:
// models/foo.js
module.exports = require('mongoose').model('Foo', ...);
// app.js
mongoose.connect(...);
// some_controller_1.js
var Foo = require('./models/foo');
Foo.find(...);
// some_controller_2.js
var Foo = require('./models/foo');
Foo.find(...);
But since I don't want to use MongoDB, I need another ORM. And all the other ORMs I have found don't allow this. You first need to create an instance, and then only you can register your models. Also they don't seem to allow access to the list of registered models.
So I tried doing this:
// models/user.js
var registrations = [];
module.exports = function(sequelize) {
var result = null;
registrations.forEach(function(elem) {
if (elem.db == sequelize)
result = elem.value;
});
if (result) return result;
// data definition
var user = sequelize.define("User", ...);
registrations.push({ db: sequelize, value: user });
return user;
};
Which I can use this like:
// some_controller_1.js
var Foo = require('./models/foo')(app.get('database'));
Foo.find(...); // using Foo
But these small header and footer that I have to write on every single model file are a bit annoying and directly violate the "don't repeat youself" principle. Also, while not a huge issue, this is kind of a memory leak since the "sequelize" object will never be freed.
Is there a better way to do, which I didn't think about?
You can find an article about handling models with sequelize here: http://sequelizejs.com/articles/express#the-application
You basically just create a models/index.js as described here: http://sequelizejs.com/articles/express#block-3-line-0
Afterwards you just put your model definitions within files in the models folder as pointed out here: http://sequelizejs.com/articles/express#block-4-line-0

Categories

Resources