How to call function on shared service - SailsJS - node.js

I have service:
module.exports = {
functionA: function () {
sails.log('Hello!');
},
functionB: function () {
functionA();
}
}
then I got an error: "countPoint is not defined"
as title, I want to call another function on shared function, but I dont now how to do. Can anyone help me?
Sorry for my bad English~

FunctionA does not "exist" yet. Remember that it is a property from a JSON, not a function per se. Using quotes should help you understand:
module.exports = {
"functionA": function () {
sails.log('Hello!');
},
"functionB": function () {
functionA(); // this is actually module.exports.functionA()
}
}
Put your functions outside module.exports and reference them without ():
module.exports = {
"functionA": functionA,
"functionB": functionA
}
function functionA() {
sails.log('Hello!');
}

#nodeman: tks for your response. But I can not call function functionA() outside of module. Then I found a solution:
file Demo.js:
module.exports = {
functionA: function () {
sails.log('Hello!');
},
functionB: function () {
Demo.functionA();
}
}
by call function with file name prefix, I called function in same module.

Related

Nodejs debug errors in production

I have a nodejs script running in production
I unlikely (once in thousand times) get errors like this:
TypeError: value is out of bounds
at checkInt (buffer.js:1009:11)
at Buffer.writeUInt16LE (buffer.js:1067:5)
at Object.foo.bar (/fake/path/name.js:123:1);
at Object.foo.bar2 (/fake/path/name2.js:123:1);
at Object.foo.bar3 (/fake/path/name3.js:123:1);
Causing the production server to crash...
Great I have a stacktrace! But I want to know what it's current data is for each call or all the data?
What are some great tools or code to use to for error logging(with it's current data) on production code?
I highly recommend in using either Winston or Bunyan. The selection of npm package is a decision of your application.
You can benchmark the available npm packages by going through the stats in the available in npm pages. The stats are basically the following.
downloads in the last day
downloads in the last week
downloads in the last month
open issues and open pull requests.
Having higher number of downloads recently will indicate that there is a great support for the module you are using in the long run. So that is important.
Both Winstan and Bunyan being best logging npm packages in the market, the main difference is that, Winstan is really awesome and flexible for normal logging purposes. Of course Winstan offers a great deal of logging capabilities. But how ever, to make use of these capabilities, some effort need to put on compared to Bunyan.
Bunyan on the other hand is specially support the fact of "analysing logs". So basically Bunyan is for logs processing. So if you want to analyse your logs, log files it is highly recommend to use Bunyan. Tweaking logs with Bunyan is fairly easy vis-a-vis to Winstan.
I did a thorough comparison between Bunyan and Winstan. Please do check the link below to view how the Winstan and Bunyan can use depending on the scope, use-case and necessity of the logging to the Node application.
link : https://docs.google.com/document/d/1pD9PLyxlcHVxxOvserNLO9tAz-QA_Co-xo6cWLhLghc/edit?usp=sharing
Also in the Production environment, make sure to use the logging levels wisely. The mostly used logging levels in production environment are:
error
info
debug
Yoou can use Winston or Pino
With winston you can load many modules for log where you want and maybe store logs online. I never use pino, but i have read good things about it.
Set env variables for choose where output your log, for example you wont to show output on stdout only if you are in develop and store online only if the app is in production.
A good way to handle the asynchronous functions in node.js is by using the decofun debug tool.
The main feature of it is to parse the code and the names of the anonymous functions according to their context.
You can deanonymise any anonymous function by running it with deco filename.js
A simple example would be as mentioned in the documentation
function gravy() {
return function returnedᅠfromᅠgravyᅠㅣlineᅠ2 () {
return {
prop: function asᅠpropertyᅠpropᅠㅣlineᅠ4 () {
setTimeout(function passedᅠintoᅠsetTimeoutᅠㅣlineᅠ5 () {
console.trace('Getting a trace...');
}, 10)
}
}
}
}
Trace: Getting a trace...
at passedᅠintoᅠsetTimeoutᅠㅣlineᅠ5 [as _onTimeout] (/home/ubuntu/workspace/node_modules/decofun/examples/loadable/index.js:6:22)
at Timer.listOnTimeout (timers.js:92:15)
Since it comes with embedded cute-stack library which normalises the path to the current directory
By applying the command deco examples/loadable --cute table
the output would be shown as
The best thing i like about it is that it transforms the functions based upon their calls to the original one as seen in the example from this
function one (a, cb) {
}
one('blah', function () {
})
function two () {
return function () { }
}
function three () {
return {
shoe: function () {}
}
}
function four () {
return function () {
return function () {
}
}
}
function five () {
return function () {
return function () {
return function () {
foo('blue', function () {
})
}
}
}
}
var six = function () {
}
var seven = function (err, cb) {
return function () {
cb(function () {
})
}
}
var o = {};
o.eight = function (cb) { }
o.eight(function () { })
o.eight.nine = function () {}
o.eight.nine(function () { })
var o2;
o2 = function () { }
;(function () {}())
!function () { }()
function toodeep () {
return function () {
return function () {
return function () {
return function () {
return function () {
return function () {
return function () {
return function () {
return function () {
return function () {
}
}
}
}
}
}
}
}
}
}
}
into this
function one (a, cb) {
}
one('blah', function passedᅠintoᅠoneᅠㅣlineᅠ6 () {
})
function two () {
return function returnedᅠfromᅠtwoᅠㅣlineᅠ11 () { }
}
function three () {
return {
shoe: function asᅠpropertyᅠshoeᅠㅣlineᅠ17 () {}
}
}
function four () {
return function returnedᅠfromᅠfourᅠㅣlineᅠ22 () {
return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠfourᅠᐳᅠㅣlineᅠ23 () {
}
}
}
function five () {
return function returnedᅠfromᅠfiveᅠㅣlineᅠ30 () {
return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠfiveᅠᐳᅠㅣlineᅠ31 () {
return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠfiveᅠᐳᅠᐳᅠㅣlineᅠ32 () {
foo('blue', function passedᅠintoᅠfooᅠㅣlineᅠ33 () {
})
}
}
}
}
var six = function asᅠvarᅠsixᅠㅣlineᅠ42 () {
}
var seven = function asᅠvarᅠsevenᅠㅣlineᅠ47 (err, cb) {
return function returnedᅠfromᅠᐸᅠasᅠvarᅠsevenᅠᐳᅠㅣlineᅠ49 () {
cb(function passedᅠintoᅠcbᅠㅣlineᅠ50 () {
})
}
}
var o = {};
o.eight = function asᅠpropertyᅠeightᅠㅣlineᅠ58 (cb) { }
o.eight(function passedᅠintoᅠoːeightᅠㅣlineᅠ61 () { })
o.eight.nine = function asᅠpropertyᅠnineᅠㅣlineᅠ63 () {}
o.eight.nine(function passedᅠintoᅠeightːnineᅠㅣlineᅠ64 () { })
var o2;
o2 = function asᅠvarᅠo2ᅠㅣlineᅠ68 () { }
;(function IIFEᅠㅣlineᅠ71 () {}())
!function IIFEᅠㅣlineᅠ73 () { }()
function toodeep () {
return function returnedᅠfromᅠtoodeepᅠㅣlineᅠ78 () {
return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠㅣlineᅠ79 () {
return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠㅣlineᅠ80 () {
return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ82 () {
return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ83 () {
return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ84 () {
return function returnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠᐸᅠreturnedᅠfromᅠtoodeepᅠᐳᅠᐳᅠᐳᅠᐳᅠᐳᅠᐳᅠㅣlineᅠ86 () {
return function () {
return function () {
return function () {
}
}
}
}
}
}
}
}
}
}
}
Hope this might help a bit! Cheers!
I am using pm2 which is a process manager for node.js and also rollbar error reporting. I think you should define some metrics for the part of your code which this error comes from.
For any uncaughtException the server will stop in order to make the server keep on running even when there is an uncaught exception what i have done is created a separate collection for storing error, save error once an uncaught exception occurs and returns.
Collection
var ErrorSchema = new mongoose.Schema({
err_Message:{type:String},
err_Stack:{type:String},
date:{type:Date}
});
Controller
process.on('uncaughtException', function (err) {
console.log(err);
console.error((new Date).toUTCString() + ' uncaughtException:', err.message);
console.error(err.stack);
var newError = new Error;
newError.err_Message = err.message;
newError.err_Stack = err.stack;
newError.date = moment();
newError.save(function(saveErr,errData){
if(!saveErr)
console.log('New Error is saved');
else
console.log('Error in saving error');
});
//process.exit(1)
});
The above methods stores the uncaught exception in the Error collection and the process/server does not stops.
Hope this helps.

How to attach parameters to a nodejs event emmiter

I've developed a way to make two separate services to comunicate using a pub/sub channel using Redis, this is the main part of the code:
var Intercom = (function () {
var _event = new events.EventEmitter();
listener.subscribe("intercom");
listener.on("message", function(channel, message) {
try {
var data = JSON.parse(message);
_event.emit(data.controller, data.payload);
}
catch (e) {}
});
return {
on: function (evt, callback) {
_event.on(evt, callback);
},
emit: function (controller, payload) {
try {
sender.publish("intercom", JSON.stringify({ controller: controller, payload: payload}));
}
catch (e) {}
}
}
})();
Im using it on the main app just by: intercom.on('hook', hookController.main);
As you can see, if the query is "hook" the main() function of hookController is called. Its a very ExpressJs like approach.
The hookController does a very simple thing:
exports.main = function(req) {
console.log(req);
}
It is not very clear to my how the parameter "req" is getting passed to main(), and probably because of my lack of understanding about it, I cant figure it out how to pass another parameter to main from the main app, something like:
var foo = 'bar';
intercom.on('hook', hookController.main, foo);
I found a way to do it;
var foo = 'bar';
intercom.on('hook', function(req) { hookController.main(req, foo) });
Its a little bit ugly.

Yeoman generator: how to run async command after all files copied

I'm writing a yeoman generator.
I need to run some shell script after all files copied.
The generator is being called as a child generator so it should wait till script finished.
The script is some command file being run via spawn:
that.spawnCommand('createdb.cmd');
As the script depends on files created by the generator it cannot run right inside generator's methods as all copy/template action are async and have not executed yet:
MyGenerator.prototype.serverApp = function serverApp() {
if (this.useLocalDb) {
this.copy('App_Data/createdb.cmd', 'App_Data/createdb.cmd');
// here I cannot run spawn with createdb.cmd as it doesn't exist
}
}
So the only place I found where I can run spawn is the 'end' event handler:
var MyGenerator = module.exports = function MyGenerator (args, options, config) {
this.on('end', function () {
if (that.useLocalDb) {
that.spawnCommand('createdb.cmd')
}
}
}
The script runs successfully but the generator finishes earlier than the child process. I need to tell Yeoman to wait for my child process.
Something like this:
this.on('end', function (done) {
this.spawnCommand('createdb.cmd')
.on('close', function () {
done();
});
}.bind(this));
But 'end' handler doesn't have the argument with 'dine' callback.
How to do this?
UPDATE:
thanks to #SimonBoudrias I got it working.
The full working code is below.
BTW: end method is described in the docs
var MyGenerator = module.exports = yeoman.generators.Base.extend({
constructor: function (args, options, config) {
yeoman.generators.Base.apply(this, arguments);
this.appName = this.options.appName;
},
prompting : function () {
// asking user
},
writing : function () {
// copying files
},
end: function () {
var that = this;
if (this.useLocalDb) {
var done = this.async();
process.chdir('App_Data');
this.spawnCommand('createdb.cmd').on('close', function () {
that._sayGoodbay();
done();
});
process.chdir('..');
} else {
this._sayGoodbay();
}
},
_sayGoodbay: funciton () {
// final words to user
}
});
Never trigger any action in the end event. This event is to be used by implementors, not generator themselves.
In your case:
module.exports = generators.Base({
end: function () {
var done = this.async();
this.spawnCommand('createdb.cmd').on('close', done);
}
});

Node module.exports reference own function like this keyword?

I have the following code:
module.exports.functionA = function(str) {
console.log(str);
}
In the same module, how do I call functionA? In other languages such as PHP, you can call another member of the same class using $this->functionA();
This does not work:
module.exports.functionA('Hello world!');
When functionA was assigned to module.exports it was still undefined. Instead do:
var functionA = function(str) {
console.log(str);
}
module.exports = {
functionA: functionA
}
Then the following will work:
module.exports.functionB = function() {
functionA('Hello world!');
}

Lifecycle of variable in AMD module

Below is the code which I saved as a file named listView.js. I wonder about how the inner variable working. For example, variable dtRngPckr is defined in the initialize within Backbone.View and whenever application move to the other part, I called onClose function to null the said variable. And when I need to reuse this module, there must be an error occur in render function. It triggered error not a function
define(function (require) {
"use strict";
var $ = require('jquery'),
_ = require('underscore'),
Backbone = require('backbone'),
dtRngPckr;
return Backbone.View.extend({
initialize: function (opt) {
dtRngPckr = require('daterangepicker');
},
render: function () {
dtRngPckr();
},
onClose: function () {
dtRngPckr = null;
}
});
});
Could someone tell me how's exactly this variable working
RequireJS caches the return value of a module so it only has to fetch it once, all prior variables are shared between the instances. To use a separate daterangepicker for each instance, you could attach it to your view:
return Backbone.View.extend({
initialize: function (opt) {
this.dtRngPckr = require('daterangepicker');
},
render: function () {
this.dtRngPckr();
},
onClose: function () {
this.dtRngPckr = null;
}
});

Resources