I am used to cross platform dev. On the C/C++ side it's simple, but I'm stuck with a problem when using javascript. I want to be able to reuse code from my web-service on the client-side. Currently node.js requires me to write my program in a most unpleasant way but I can handle it:
//MyClass.js
function MyClass()
{
this.test = function(){}
}
module.exports.MyClass = MyClass;
//server.js
var m = new require('MyClass.js').MyClass();
m.test();
//client.js
$.getScript("MyClass.js", function(){
var m = new MyClass();
m.test();
});
To that point it is all fine, but I have an issue when I need to load classes from MyClass.js. How can I make it work across all the platforms? Is there a way to achieve reusability without processing the files?
Node requires you to do nothing. If you aren't a fan of the way the Node module system works, simply don't use it.
//MyClass.js
MyClass = function ()
{
this.test = function(){}
}
//server.js
require('./MyClass.js');
var m = new MyClass();
m.test();
Now your application is compatible with what you have going on client-side. Just bear in mind that you are now creating classes in the global namespace, which is one reason for using Node's module layout.
I suggest also looking into some of the ways to use a Node-style require on the client. There are many scripts available, such as RequireJS or Browserify.
Related
Im new to using classes in JS and been trying to find the best practices for it and was wondering how requires work when using it in the class.
Say I wanted to create an IoT Connection class to use to make connection to the azure iot hub. In order to make connections i need some requires to get the function getClientFromConnectionString.
var Protocol = require('azure-iot-device-amqp').Amqp;
var clientFromConnectionString = require('azure-iot-device-amqp').clientFromConnectionString;
class IoT_Connection {
constructor(_deviceName, _securityKey1, _securityKey2) {
this.deviceName = _deviceName;
this.securityKey1 = _securityKey1;
this.securityKey2 = _securityKey2;
}
}
module.exports = IoT_Connection;
var conn = new IoT_Connection("z", "x", "y");
What happens when i create a new instance of the class? Does the require load only once or would be a problem if i was making hundreds of connections every few minutes?
Is there a better approach to this problem?
Yes; whenever your run your nodejs server your code is interpreted by javascript engine(in this case the very V8 engine) it will interpret your code. The file which is require by any of the starting file(server.js or app.js) will be interpreted and the require statements will be executed only once.
So,
var clientFromConnectionString = require('azure-iot-device-amqp').clientFromConnectionString;
will make only one connection.
To understand better of 'how module.exports and require work' create an empty file and do some console.log('foo') in there and require it in your existing code.
I'm running against a wall here, maybe it's just a small problem where I can't see the solution due to my inexperience with NodeJS.
Right now I'm constructing a BT device which will be controlled by a master application and I have settled for the prototyping on a Raspberry PI 3 with NodeJS using the Bleno module.
So far everything worked fine, the device gets found and I can set and get values over Bluetooth. But to separate the different "programs" which the device could execute from the Bluetooth logic (because of loops etc.) I have opted to extract these into external NodeJS files.
The idea here was to use the NodeJS fork module and control the starting and stoppping of those processes through the main process.
But herein my problems start. I can fork the different JavaScript files without problem and these get executed, but I can't get them to stop and I don't know how to fix it.
Here's the code (simplified):
var util = require('util');
var events = require('events');
var cp = require('child_process');
...
var ProgramTypeOne = {
NONE: 0,
ProgramOne: 1,
...
};
...
var currentProgram=null;
...
function BLEDevice() {
events.EventEmitter.call(this);
...
this.currentProgram=null;
...
}
util.inherits(BLELamp, events.EventEmitter);
BLELamp.prototype.setProgram = function(programType, programNumber) {
var self = this;
var result=0;
if(programType=="ProgramTypeOne "){
if(programNumber==1){
killProgram();
this.currentProgram=cp.fork('./programs/programOne');
result=1;
}else if(programNumber==2){
...
}
self.emit('ready', result);
};
...
module.exports.currentProgram = currentProgram;
...
function killProgram(){
if(this.currentProgram!=null){
this.currentProgram.kill('SIGTERM');
}
}
There seems to be a problem with the variable currentProgram which, seemingly, never gets the childprocess from the fork call.
As I have never worked extensivley with JavaScript, except some small scripts on websites, I have no idea where exactly my error lies.
I think it has something to do with the handling of class variables.
The starting point for me was the Pizza example of Bleno.
Hope the information is enough and that someone can help me out.
Thanks in advance!
Since killProgram() is a standalone function outside of the scope of BLELamp, you need to call killProgram with the correct scope by binding BLELamp as this. Using apply (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) should resolve it. The following I would expect would fix it (the only line change is the one invoking killProgram):
BLELamp.prototype.setProgram = function(programType, programNumber) {
var self = this;
var result=0;
if(programType=="ProgramTypeOne "){
if(programNumber==1){
killProgram.apply(this);
this.currentProgram=cp.fork('./programs/programOne');
result=1;
}else if(programNumber==2){
...
}
self.emit('ready', result);
};
As a side note, your code is kind of confusing because you have a standalone var currentProgram then a couple prototypes with their own bound this.currentPrograms. I would change the names to prevent confusion.
I have my code:
var User = function() {
...
}
and the test code using IIFE:
(function() { // test new user
var user = new User();
if (typeof user === 'undefined') {
console.log("Error: user undefined");
}
...
}());
both in the same js file. Works great! But, as the program grows, this is becoming too refractory for me to manage, as I have a piece of test code for every piece of business logic.
I've been taught to keep all my js in the same file, (minified is good) in production, but is there a best-practical way to keep my test code in a different file during development?
I was thinking I could use a shell script to append the test code to the production code when I want to run the tests, but I'd prefer a cross-platform solution.
I don't want or need a framework solution, I want to keep it light -- does node have anything built-in for this sort of thing?
Node has two expressions for this case. First:
module.exports = name_of_module;
Which is to export module for example function, object or something similar. And the second:
var module_name = require('Path/to/module');
to import it from other file. If you want to export IIFE you must assign it to global variable and module.export name of variable.
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
So I've been playing with JS and browserify to allow to split my JS into smaller file chunks. It works great, however, I'm still lost on how to properly use the require function.
For me, it acts as a the Service Locator, because it looks for the proper "file" to load, and return an object. (For example in PHP, require somewhat load the file in the memory but doesn't construct).
Example:
var Foo = function() {
console.log("I'm the Foo object");
};
module.exports = Foo;
Then, to use it I'll do:
var Foo = require('foo');
and
var foo = new Foo();
Note, that the exported function is NOT constructed.
I could have done:
var foo = require('foo')();
None of those methods seems right to me (I may are wrong).
1) Is it common to do it like this? Or should exported the executed function?
Anyway, this introduction is to understand how I should play with the require function.
For example if I've a Foo object, which is depends of Bar, I've two way to do:
Service Location:
var Foo = function() {
var Bar = require('bar')();
Bar.doSomethingAwesome();
};
module.exports = Foo;
or I can do:
Dependency Injection
var Foo = function(bar) {
bar.doSomethingAwesome();
};
module.exports = Foo;
// And at a latter time
var foo = require('foo')(require('bar')); /// eurk
I obviously know that that's two different things and serve different purposes.
2) But I'm wondering what is the common/right way to do in JS, is there any commonly admitted rules?
Browserify allows you to program with modules, there's not much more to it. It's not really a DI container or service locator per se, although you can probably make it work like one.
So doing this is perfectly fine:
var Foo = require('foo');
var foo = new Foo();
In that case, it makes sense to simply place all require calls at the top of your file, similar like you would do with using in C# or import in Java. I personally wouldn't scatter require calls since don't help much with readability.
You can also export an instance which doesn't have to be newed up anymore, as long as that is appropriate for what you want to do (in that case module.exports = Foo() would lead to a singleton).
Also see this related question:
Dependency Injection with RequireJS
The rewire library provides module injection for Node.js.
A couple of solutions have been discussed and presented in this Github issue to support browserify.
Usage example from the project README:
var myModule = rewire("../lib/myModule.js");
myModule.__set__("fs", fsMock); // set private variable
Use Browserify so you can require npm packages from your browser just like node. Then you can use Weather.js or require it, then inject it in any way you like.