Node.js performance - node.js

Imagine, we got 2 simple classes (omitted export):
class SomeService {
async func () {
// some async function logic
return value;
}
}
class SomeController {
constructor (service) {
this.service = service;
}
async func () {
const value = await this.service.func();
// some controller-specific logic here
return value;
}
}
Also, we got simple function, that use this two classes in two ways.
Case one:
// require clasess
const somefunc = async () => {
const controller = new SomeController(new SomeService());
const value = await controller.func();
return value;
}
module.exports = somefunc;
Case two:
// require clasess
const controller = new SomeController(new SomeService());
const somefunc = async () => {
const value = await controller.func();
return value;
}
module.exports = somefunc;
As far as i understand how node's require works in the first case controller will be created each time when the somefunc is called. In the second case controller is created only one time, when the file will be evaluated. What case is better and more importantly what should i read or lookup to understand why?

I imagine the answer depends on your use-case. You have to ask yourself if you need to recreate SomeController every time that the function is called or not. Another thing to also consider is whether SomeController relies on something async when being initialized. For instance, if the controller needs access to a database connection in its constructor, then you'd have to wait for the database connection to be established. In situations like that, you may have no choice but to initialize SomeController inside the function. As I said, there's no objective better in cases like this. It's all dependent on your use-case.

Related

What is the difference between a singleton and a module that instantiates an instance?

I want to add a metrics class to my code. What is the difference between
class MyMetrics {
constructor () {
if (!Singleton.instance) {
Singleton.instance = new Metrics()
}
return Singleton.instance
}
}
const metrics = new MyMetrics()
and
export const metrics = new Metrics()
Wouldn't each module that imported metrics be using the same Metrics instance?
Are they functionally the same for my usage? Which would be recommended?
Wouldn't each module that imported metrics be using the same Metrics instance?
Yes, they would.
Are they functionally the same for my usage?
As long as A) you aren't creating other instances within the module and B) you aren't exporting Metrics, yes, almost. But one thing to remember is that any code that has access to your metrics import has access to your Metrics constructor, indirectly via the constructor property metrics inherits from Metrics.prototype:
import { metrics } from "./your-module.js";
const newMetrics = new metrics.constructor();
You might think that with the singleton, you've avoided that, but that's easily defeated as instance is public:
import { metrics } from "./your-module.js";
const Metrics = metrics.constructor;
Metrics.instance = null;
const newMetrics = new Metrics();
So you might want to make it private (either using a static private property, or just using metrics itself to check if you've created it).
Which would be recommended?
That's a matter of opinion. But you might not even need a class at all. You could:
Just make an object directly without a constructor function.
Export functions and close over module-private variables.
For instance, consider this (fairly silly) class:
// stuff.js
class Stuff {
#items = new Map();
constructor() {
// ...pretend there's singleton logic here...
}
put(key, value) {
this.#items.set(key, value);
}
get(key) {
return this.#items.get(key);
}
}
export const stuff = new Stuff();
The way you use that is:
import { stuff } from "./stuff.js";
stuff.put("this", "that");
stuff.get("this"); // "that"
You could just get rid of the class entirely:
// stuff.js
const items = new Map();
export const stuff = {
put(key, value) {
items.set(key, value);
},
get(key) {
return items.get(key);
}
};
Usage would be the same:
import { stuff } from "./stuff.js";
stuff.put("this", "that");
stuff.get("this"); // "that"
Or you could just export put and get:
// stuff.js
const items = new Map();
export const put = (key, value) => {
items.set(key, value);
};
export const get = (key) => items.get(key);
Then usage is:
import { get, put } from "./stuff.js";
put("this", "that");
get("this"); // "that"
Or if those names may conflict with other things:
import { get as getStuff, put as putStuff } from "./stuff.js";
putStuff("this", "that");
getStuff("this"); // "that"
So you have lots of options to choose from. Constructor functions (including ones created with class syntax) are useful if you need to construct multiple objects with shared characteristics, but if you aren't doing that (and you aren't with a singleton), just writing the object directly or (with modules) exporting the things it can do directly may be good options for you.

Stackable functions

I am looking for a library agnostic way to "stack" functions. The paradigm's I am used to is "middleware", where something happens within a function errors can be thrown, and a context (or req) global is used to attach new properties or change existing ones. These ideas are found in libraries like express, or type-graphql.
I am looking for some agnostic way to chain middleware, not dependent on these type of libraries.
Here's an example of the kinds of functions I have.
I am struggling with some kind of clean way to author functions. The global approach is not complimentary to proper typing using typescript, and isn't very functional.
Where the more functional approach lacks this kind of "chainablity", where I can simply have an array of functions like below.
// logs the start of middleware
context.utility.log(debug, ids.onLoad),
// fetches user by email submitted
context.potentialUser.fetchByEmail(SignupOnSubmitArgs),
// throws error if the user is found
context.potentialUser.errorContextPropPresent,
// checks if passowrd and reenterPassword match
context.potentialUser.signupPassword(SignupOnSubmitArgs),
// creates the user
context.user.create(SignupOnSubmitArgs, ''),
// thows error if create failed in some way
context.user.errorContextPropAbsent,
// adds user id to session
context.utility.login,
// redirects user to dashboard
context.utility.redirect(Pages2.dashboardManage)
Is there any tools / libraries out there that will allow be to author clear and clean chain-able functions, and glue them together in a stackable way?
Returning this is usually the way for being able to chain methods. I made you an example showing both sync and async functions:
class ChainedOperations {
constructor(private value: number){}
public add(n: number): this {
this.value += n;
return this;
}
public subtract(n: number): this {
this.value -= n;
return this;
}
public async send(): Promise<this> {
console.log(`Sending ${this.value} somewhere`);
return this;
}
}
async function somewhereElse(): Promise<void> {
const firstChain = await new ChainedOperations(1).add(1).subtract(1).send();
await firstChain.add(1).subtract(2).send()
}
somewhereElse().catch(e => { throw new Error(e) });
For better dealing with async functions you can use pipe pattern where you chain but also wait for the final result and pass it to the next guy:
abstract class Pipable {
public pipe(...functions: Function[]) {
return (input: any) => functions.reduce((chain, func: any) => chain.then(func.bind(this)), Promise.resolve(input));
}
}
class AClass extends Pipable {
constructor(private value: number){
super();
}
public add(n: number): number {
this.value += n;
return this.value;
}
public subtract(n: number): number {
this.value -= n;
return this.value;
}
public async send(): Promise<number> {
console.log(`Sending ${this.value} somewhere`);
return this.value;
}
}
async function Something(){
const myClass = new AClass(2);
const composition = await myClass.pipe(myClass.add, myClass.subtract, myClass.send)(2);
}
Something();
Some people don't like to start from beginning but work their way backwards from the last function. If you want that just replace .reduce with .reduceRight. If you like fancy names, starting from last is called Composing as opposed to piping.

Instantiate object after promisified import

I am struggling to instantiate object from dynamically imported classes. Basically I have some plugins which kinda look like this:
export interface IPlugin {
compile(logEvent: LogEventInfo): string;
}
export class DatePlugin implements IPlugin {
public compile(logEvent: LogEventInfo): string {
const date: Date = new Date();
return `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
}
}
In another file I want to dynamically crawl a folder, load all source files and instantiate them. I saw that import(...).then() can return a loaded object however in my case it returns the class and my object creation starts looking very ugly:
public async loadPlugins(): Promise<void> {
// ...
await Promise.all(pluginFiles.map(async (pluginFile: string): Promise<void> => {
const pluginFilePath: string = path.join(pluginsFolder, pluginFile);
import(pluginFilePath).then((plugin: any): void => {
const obj: IPlugin = (new plugin[Object.keys(plugin)[0]]() as IPlugin;
// ...
});
}));
}
Isn't there any better way to instantiate all those classes when loading them?
import() promises aren't chained, this is a mistake similar to this case that may result in problems with error handling and race conditions.
map shares a common potential problem with this case. It's used only to provide promises to wait for them, but not actual values. Since the purpose of async function call is to get class instance, it's reasonable to map pluginFile input to obj output value if it's supposed to be stored then - or compile result if it isn't:
public async loadPlugins(): Promise<...> {
const plugins = await Promise.all(pluginFiles.map(async (pluginFile: string): Promise<IPlugin> => {
const pluginFilePath: string = path.join(pluginsFolder, pluginFile);
const pluginExports = await import(pluginFilePath);
// preferably pluginExports.default export to not rely on keys order
const Plugin: { new(): IPlugin } = Object.values(pluginExports)[0];
return new Plugin();
}));
...
}
The only real benefit that import provides here is that it's future-proof, it can seamlessly be used natively in Node.js with third-party ES modules (.mjs) files. Since TypeScript is used any way and uses require for ES module imports under the hood, it may be reasonable to discard asynchronous routine and use require synchronously instead of import for dynamic imports:
public loadPlugins(): <...> {
const plugins = pluginFiles.map((pluginFile: string): IPlugin => {
const pluginFilePath: string = path.join(pluginsFolder, pluginFile);
const pluginExports = require(pluginFilePath);
// preferably pluginExports.default export to not rely on keys order
const Plugin: { new(): IPlugin } = Object.values(pluginExports)[0];
return new Plugin();
}));
...
}

Why is the constructor invoked despite calling createStubInstance?

I want to prevent the constructor of a class being called during a test so I used createStubInstance(MyClass) as per the docs, but the constructor still gets invoked. Why?
If you want to create a stub object of MyConstructor, but don’t want
the constructor to be invoked, use this utility function.
var stub = sinon.createStubInstance(MyConstructor)
Test
const sinon = require('sinon')
const Fizz = require('../Fizz')
const Buzz = require('../Buzz')
describe('Fizz', () => {
it('should mock the constructor', () => {
sinon.createStubInstance(Fizz)
const doStuffFakeFizz = sinon.stub(Fizz.prototype, 'doStuff').returns({ src: 'mock' })
const buzz = new Buzz()
buzz.doStuff()
expect(doStuffFakeFizz.called).toBeTruthy()
})
})
Buzz
const Fizz = require('./Fizz')
class Buzz {
doStuff() {
const fizz = new Fizz()
return fizz.doStuff()
}
}
module.exports = Buzz
Fizz
class Fizz {
constructor() {
console.log('CALLED')
this.thing = { src: 'real' }
}
doStuff() {
return this.thing
}
}
module.exports = Fizz
sinon.createStubInstance can't replace references like that. All it does is return a plain object with a stub in place for each property in the constructor's prototype. You'll usually make this object the return value of some stub, or provide it as an argument somewhere, in order to get it into place.
In order to actually stub the Fizz constructor, your code under test needs to invoke it by means of a reference that can be replaced. See my answer here:
Can ES6 constructors be stubbed more easily with Sinon?

How to call remove listener on EventEmitter in nodejs?

I have below code to add listeners on EventEmitter,
class MyClass {
init() {
this.listener = new EventEmitter();
this.listener.on('eventName', this.onChange.bind(this));
}
onChange() {
...
}
}
How can I remove the listener from EventEmitter? I can see two different ways:
this.listener.removeListener('eventName', this.onChange)
this.listener.removeListener('eventName', this.onChange.bind(this))
I wonder which one I should use. Whether I need the bind when I remove it?
You can use bind() or you can use an Arrow Function in Node. Arrow Functions will inherit their execution context from the invoking context, which is similar to how bind() works and provides the same functionality.
this.listener.removeListener('eventName', this.onChange)
The above way of removing a listener won't work if it is being called in a removeListener(eventName) style function like the following:
const obj = new MyObject()
obj.init()
// This would blow up with a
// ReferenceError saying you cant call removeListener() on undefined
obj.listener.removeListener('event')
Not sure the use of the init() function when you can use a constructor with the class syntax.
constructor() {
this.listener = new EventEmitter()
this.boundEventNameHandler = () => this.onChange()
this.listener.on('eventName', this.boundEventNameHandler)
}
You can utilize the bound function for removing a listener within the context of a class using this.
let boundEventNameHandler = this.boundEventNameHandler
this.listener.removeListener('eventName', this.boundEventNameHandler)`
An example of this implemented looks like the following
const EventEmitter = require('events')
class MyObject {
constructor () {
this.listener = new EventEmitter()
this.boundEventNameHandler = () => this.onChange()
this.listener.on('eventName', this.boundEventNameHandler)
}
// I would reconsider making this a property of the MyObject class
// instead, make onChange() a local function outside the MyObject
// class definition because onChange in this example is only used by the
// event listener for 'eventName'
onChange () {
console.log('event fired change')
}
removeListeners () {
let boundEventNameHandler = this.boundEventNameHandler
this.listener.removeListener('eventName', boundEventNameHandler)
}
}
For TypeScript / ESNext you can use this:
class MyClass {
constructor() {
this.emitter = new EventEmitter();
this.emitter.on("event1", this.listener1);
this.emitter.on("event2", this.listener2);
this.emitter.removeListener("event1", this.listener1);
this.emitter.removeListener("event2", this.listener2);
this.emitter.emit("event1"); // no output
this.emitter.emit("event2"); // no output
}
public listener1 = (e) => {
console.dir(`listener1`);
};
public listener2 = (e) => {
console.dir(`listener2`);
};
}
Basically you define properties and instantly assign bound functions to them.
This way you use the same function reference in .on and .removeListener.

Resources