How to expand nodejs module - javascript

I would like to expand nodeJs module.
For example, I want to add a function into Utilities module.
like detect empty JSON object
function isEmptyObject(obj) {
return !Object.keys(obj).length;
}
So, I can use util.isEmptyObject() to detect empty JSON object.
Is it a good way to expand nodeJs module?

You can extend "utils" with defining your "UtilEx" module:
/* utils_ex.js */
var utils = require('utils');
utils.isEmptyObject = function() { };
exports = module.exports = utils;
/* end of utils_ex.js" */
/// client js
var utils = require('utils_ex');

Related

Getting "TypeError: Dropdown is not a function" when trying to use a class in protractor

I'm getting "TypeError: Dropdown is not a function when trying to do the following:
/*
* Dropdown.js
*/
var __container;
function Dropdown(el) {
__container = el;
}
Dropdown.prototype = {
constructor: Dropdown,
getOptions: function() { return __container.element.all(by.css('option')); },
// my other prototype methods
}
--
/*
* PageObject.js
*/
var Dropdown = require('Dropdown');
var PageObject() {}
PageObject.prototype = {
constructor: PageObject,
myDd: new Dropdown(element(by.css('select')),
//my other prototype methods which do work
};
--
/*
* spec.js
*/
var PageObject = require('PageObject');
describe('Test my page', function() {
it('should test the dropdown', function() {
browser.get(mypage);
var pageObject = new PageObject();
expect(pageObject.myDd.getOptions().isPresent()).toBe(true);
});
});
as #11684 mentioned - you've forgot to export your Dropdown and PageObject classes and require('Dropdown'); returns undefined. Protractor is run on node.js so you need to fill the gaps about CommonJS modules. Also if you want to require modules which are not installed with npm you have to target them using relative paths so rather than
var PageObject = require('PageObject');
you'd need to do something like
var PageObject = require('./pages/PageObject');
var Dropdown = require('../helpers/Dropdown');
etc.
and to export a module in node environment using commonJS modules you need to either export them as set of properties/methods set on the exports object or you can assign your constructor directly to it so it's available directly on the required module
// in Dropdown
module.exports = Dropdown;
// in PageObject
module.exports = PageObject;
If you plan to use more of node.js in your testing you should read bit more about working with commonJS modules https://nodejs.org/docs/latest/api/modules.html and on node.js itself in general. Would recommend checking out what from ES6 you can use already http://node.green/ to make your tests more organised and readable as well

CommonJS module pattern

I have taken this from
Flux architecture
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var TodoConstants = require('../constants/TodoConstants');
var assign = require('object-assign');
var CHANGE_EVENT = 'change';
var _todos = {}; // collection of todo items
/**
* Create a TODO item.
* #param {string} text The content of the TODO
*/
function create(text) {
// Using the current timestamp in place of a real id.
var id = Date.now();
_todos[id] = {
id: id,
complete: false,
text: text
};
}
/**
* Delete a TODO item.
* #param {string} id
*/
function destroy(id) {
delete _todos[id];
}
var TodoStore = assign({}, EventEmitter.prototype, {
/**
* Get the entire collection of TODOs.
* #return {object}
*/
getAll: function() {
return _todos;
},
emitChange: function() {
this.emit(CHANGE_EVENT);
},
/**
* #param {function} callback
*/
addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
},
/**
* #param {function} callback
*/
removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
dispatcherIndex: AppDispatcher.register(function(payload) {
var action = payload.action;
var text;
switch(action.actionType) {
case TodoConstants.TODO_CREATE:
text = action.text.trim();
if (text !== '') {
create(text);
TodoStore.emitChange();
}
break;
case TodoConstants.TODO_DESTROY:
destroy(action.id);
TodoStore.emitChange();
break;
// add more cases for other actionTypes, like TODO_UPDATE, etc.
}
return true; // No errors. Needed by promise in Dispatcher.
})
});
where it says
There are a few important things to note in the above code. To start, we are maintaining a private data structure called _todos. This object contains all the individual to-do items. Because this variable lives outside the class, but within the closure of the module, it remains private — it cannot be directly changed from outside of the module. This helps us preserve a distinct input/output interface for the flow of data by making it impossible to update the store without using an action.
The bold part is unclear to me. How can js interpreter know that all those code is inside a module closure and not in the globals scope?
From where the module closure start and where ends?
As far as I know
The scope of a variable declared with var is its current execution context, which is either the enclosing function or, for variables declared outside any function, global.
Any explanation?
You're actually missing the last line from the extract you quoted :
module.exports = TodoStore;
CommonJS is an API to define modules that use the following conventions :
Every file defines a module and is executed in an isolated environment ; that is to say that the variables it defines won't be available from outside the module.
To allow importing other modules, a global variable require is made available to the module, allowing it to import other modules
In the same way, the variable module is made available to the module so that it can set its exports attribute to define what should be exported by your module ; the value you set for module.exports in your module a.js is exactly what require('./a') will return.
Every JS environment that implements CommonJS has to know these rules. That includes Node.js, of course, but also bundlers like Browserify and Webpack that will package your codes so that these conventions are respected.
This way, you can control which part of your module will be exported.
P.S. : note that you can also use the exports var to define your exports, and that its use is slightly different from module.exports. See this StackOverflow question and answer for details
Common JS pattern uses the constructor function to define your utilities.
It is defined in the form of class.
var moduleName = function() {
// private variables
// public functions
this.method1 = function() {
// logic1 goes here
};
this.method2 = function() {
// logic2 goes here
};
};
So we are going to export the class to other modules using
module.exports = moduleName;
So that other modules can import it, instantiate it and then use the functionality.
How to use it?
var module = require('moduleName'); //importing the module created above
Here the module definition is fetched,executed and then available in 'module' variable.
This variable name can be anything
var objectOfModule = new module(); //instance is created
objectOfModule .method1(); //use1
console.log(objectOfModule .method2()); //use2
Thanks.

How to Augument commonjs module from requiring code?

I am wondering how I can augument a commonjs module from another module that requires it.
Let's assume that I have three files, two commonjs modules as below:
my-example-module.js
function MyExampleModule(){}
MyExampleModule.prototype = {
bindings: {
some: 'random',
prop: 'values'
}
}
module.exports = MyExampleModule;
another-example-module.js
var MyExampleModule = require('./my-example-module');
function AnotherExampleModule(){}
AnotherExampleModule.prototype = {
getMyExampleModuleBindings: function(){
var module = new MyExampleModule();
return module.bindings;
}
}
module.exports = AnotherExampleModule;
app.js
var MyExampleModule = require('./my-example-module');
var AnotherExampleModule = require('./another-example-module');
//modify?!?
var anotherExampleModule = new AnotherExampleModule();
console.log(anotherExampleModule.getMyExampleModuleBindings());
So what I want to do is have //modify?!? be some kind of code that will alter the original MyExampleModule prototype so when anything else attempts to require MyExampleModule it will get the modified version.
A concrete question would be - what should I replace //modify?!? with so I get logged out the the console with the assumption that my-example-module.js is read only.
{
some: 'random',
prop: 'values',
added: 'binding'
}
If you want to do this in nodejs/iojs, this is pretty simple. When node imports a CommonJS module (let's call it A), it creates an internal object.
When another module (B) wants to load the same module (A), it just gets the reference to that internal object. So if you change something on MyExampleModule in app.js it is also applied to the MyExampleModule in another-example-module.js:
app.js
var MyExampleModule = require('./my-example-module');
var AnotherExampleModule = require('./another-example-module');
//modify:
MyExampleModule.prototype.bindings = {
some: 'random',
prop: 'values',
added: 'binding'
};
var anotherExampleModule = new AnotherExampleModule();
console.log(anotherExampleModule.getMyExampleModuleBindings());
Since you create a new instance of MyExampleModule in another-example-module.js after you call MyExampleModule.prototype.bindings = {...} in app.js, the new instance will already be created with the modified .prototype.
While I haven't tested this in browserify, it certainly works in webpacks implementation of CommonJS as well.
Check out the working example on runnable (app.js is called server.js):
http://code.runnable.com/VZPdN5k65gE5vUIz

Requirejs dynamic reference to sub module methods?

Using requires, I’ve split larger class structures down into modules that use other modules within directory. There’s a main file that instantiates the other sub modules. This is an API class with two modules. One that deals with posting data to the endpoint, and the other that holds functions that are helpers to that post module:
define([
'./Post',
'./Helper'
], function (PostModule, HelperModule) {
'use strict';
var module = function () {
this.Post = new PostModule();
this.Helper = new HelperModule();
};
return module;
});
Now I can chain these modules like this:
var foo = new ApiModule();
foo.Post.postToAPI();
foo.Helper.matchAPIactionToEvent();
which is exactly what I want..
BUT, the problem is within the Post.js file, is that it doesn’t know anything about the Helper.js file. So I can’t take advantage of any of those methods. What I would like to do within the Post.js file is to be able to reference the other functions within the same class like so:
define([
'../environment',
'loglevel',
'../utility/Utility',
'jquery'
], function (EnvironmentModule, log, UtilityModule, $) {
'use strict';
var module = function () {
var environment,
utility,
api;
environment = new EnvironmentModule();
utility = new UtilityModule();
this.postToAPI = function (event, payload, callback) {
var apiEndpoint,
requestIdString,
eventAndAction;
apiEndpoint = environment.getEnvironmentPath().API;
requestIdString = utility.String.generateRandomString(32);
/*** THIS IS HOW I WANT TO CALL THE HELPER METHODS ***/
eventAndAction = this.Helper.matchAPIactionToEvent(event);
/*** THIS IS HOW I WANT TO CALL THE HELPER METHODS ***/
payload.event = eventAndAction.event;
payload.action = eventAndAction.action;
payload.requestID = requestIdString;
payload = $.param(payload);
$.post(apiEndpoint + '?' + payload, function (result) {
if (callback) {
callback(result);
}
});
return;
};
};
return module;
});
I figured out a working solution to the this, where I pass '../api/Helper' as one of the array values in the define statement of Post.js; but I don’t want to do that. What I want is to have Post.js be able to access any method from any other modules that are contained within the same directory. That way I don’t have to explicitly define them. It seems wrong to instantiate a new ApiModule() within Post.js. Here’s the directory structure:
Modules/api/Api.js
Modules/api/Post.js
Modules/api/Helper.js
...
I hope that makes sense. Is this possible?
Since you want any of the child modules to access any other child modules, what you could do is pass the parent module as an argument to the constructors of the child modules:
var module = function () {
this.Post = new PostModule(this);
this.Helper = new HelperModule(this);
};
Have the child modules store this information:
var module = function (parent) {
this.parent = parent;
Then use this this.parent to call the methods on other child modules:
eventAndAction = this.parent.Helper.matchAPIactionToEvent(event);
Note that if you would load '../api/Helper' with RequireJS in Post.js as you were thinking of doing, you would not be able to use the same object instance as the one defined on the parent module. You'd have to construct a new object for use in Post.js.

Node js and new when using require

I've been trying to sort out the include of other js files within node.js.
I've read all about the require function and other alternatives and decided to go with the require function (as the code will only ever be used on node.js, not in a browser).
In my code I'm using prototypes to create an 'object' which I later wish to create an instance off.
To get it to work I've been writing code like the following (lets call it vehicle.js):
var util = require('util');
var EventEmitter = require('events').EventEmitter;
module.exports = Vehicle;
util.inherits(Vehicle, EventEmitter);
function Vehicle(options) {
EventEmitter.call(this);
options = options || {};
...
}
Vehicle.prototype._doStartEvent = function(data) {
this.emit('start', data);
};
Vehicle.prototype.testRun = function() {
this._doStartEvent();
};
Then in my main js (lets call it server.js), I have the following:
var test = exports;
exports.Vehicle = require('./vehicle.js');
var remoteVehicle = new test.Vehicle({address: "192.168.1.3"});
remoteVehicle.on('start', function(d) {console.log('started');});
remoteVehicle.testRun();
Now this all works fine, but I do not have a good understanding of what is going on.
My main concern is the use of var test = exports; and then exports.Vehicle = require(...).
I tried just doing something like var vehicle = require(...).Vehicle and var vehicle = require(...), with the goal of just using new Vehicle or similar, but I couldn't get it to work.
Am I forced to use exports and if so why?
Please note I've been using the AR Drone project as an example, the above code is based on how they have done their modules internally. Refer to Client.js and index.js.
result of require is a reference to exports object which is function in your case. Just assign to a variable with the same name as class (or any other) and use as a parameter to new
var Vehicle = require('./vehicle.js');
var remoteVehicle = new Vehicle({address: "192.168.1.3"});
remoteVehicle.on('start', function(d) {console.log('started');});
remoteVehicle.testRun();

Categories