refactor NodeJs functions - javascript

I have a big app.js file and want to split the code. I took all my routes into a module called routes.js
module.exports = function(app){
app.get('/', function (req, res) {
res.redirect('/page1');
});
app.get('/page1', function (req, res) {
res.render('page1');
});
app.get('/page2/:id', function (req, res) {
res.render('page2', {
val: Number(req.params.id)
});
});
}
and in my app.js I call
const routes = require('./Server/routes')(app);
So this works fine.
I have some functions like
function loadData(id, callback) {
fs.readFile('./database.json', 'utf8', function (err, data) {
var json = JSON.parse(data);
var arr = json.arr;
var obj = arr.find(e => e.id === Number(id));
callback(obj);
});
}
and want to have them in separate files too. How can I do this? I am able to export one function but how can I export more than one?
Like
module.exports = function(){
function sayHello(){
console.log("Hello");
}
function calc(){
return 5 + 7;
}
}
require the module and call
myModule.sayHello();
var num = myModule.calc();

In your new module you can export an object and define your functions inside object
module.export = {
sayHello: function() {
console.log("Hello");
},
calc: function() {
return 5 + 7;
}
}
// usage: const mymodule = require('path/to/your/file');
also you can export a function and define your needed functions in prototype
function mymodule(someArgsIfNeeded) {
// do some initialization
}
mymodule.prototype.sayHello = function() {
console.log("Hello");
}
mymodule.prototype.calc = function() {
return 5 + 7;
}
module.export = mymodule
// usage: const mymodule = require('path/to/your/file')(someArgsIfNeeded);

Related

How to Import function in node.js?

I want have 2 functions in report.js file I want to one is report_data which is api controller and second is test I want to use test function in report_data function.
Below is my code of both functions.
var sequelize = require('../config/sequelize');
const Op = sequelize.Sequelize.Op;
var errors = require('../config/errors');
var error = errors.errors;
const helpers = require('../helpers/validations');
const logger = require('../helpers/logger').logger;
const fs = require('fs');
module.exports = {
report_data: async (req, res) => {
if (!req.body.id) {
logger.warn(error.MANDATORY_FIELDS);
return res.status(500).send(error.MANDATORY_FIELDS)
}
sequelize.sequelize.transaction(async (t1) => {
console.log('socket connected')
test(io)
let result = error.OK
logger.info(result);
return res.status(200).send(result)
}).catch(function (err)
logger.warn(err);
console.log(err)
return res.status(500).send(error.SERVER_ERROR)
})
},
test: function (io) {
console.log(io.sockets)
}
};
The easiest would be to declare test as a named global function:
function test(io) {
console.log(io.sockets)
}
module.exports = {
report_data: async (req, res) => {
// now you call call `test()` here
},
test: test,
}

Passing arguments to callback function with in a separte module

I would create a new separate module with a function that contains a callback that I call in main file.
My program should take 3 args: first a file directory, then file extention and finally a callback function that should filter a directory by fileextension.
Here's my module.js file
var fs = require('fs')
module.exports = function (directory, fileExtension, callbackfun) {
fs.readdir(directory, callbackfun);
}
then in main file I import module then use function.
modulejs(process.argv[2], process.argv[3], callbackfun(callbackfn));
var callbackfn = function (err, data, fileExtension) {
console.log(fileExtension);
let filtred = data.filter(file => { if (file.indexOf("." + fileExtension) > -1) { console.log(file); } });
};
function callbackfun(callbackfunc1) {
callbackfunc1(err, data, fileExtension);
}
The error that I get actually is
ReferenceError: err is not defined
UPDATE: I have edited my code, I get different error now
UPDATE2: I get the solution on internet but does not understand how it works, if anyboby explain it to me step by step it would be nice
module.jsconst fs = require('fs')
const path = require('path')
module.exports = function (dir, filterStr, callback) {
fs.readdir(dir, function (err, list) {
if (err) {
return callback(err)
}
list = list.filter(function (file) {
return path.extname(file) === '.' + filterStr
})
callback(null, list)
})
}
main.js
const filterFn = require('./module.js')
const dir = process.argv[2]
const filterStr = process.argv[3]
filterFn(dir, filterStr, function (err, list) {
console.log(list);
if (err) {
return console.error('There was an error:', err)
}
list.forEach(function (file) {
console.log(file)
})
})

Node Js web services with visual studio 2017

Hi I'm used to work with c#, I'm new with node js. I'm trying to create some kind of web service using Node Js. I'm using VS 2017 community with node js version 8. I have next code:
Express App1
apps.js
app.param('phone', function (request, response, next, phone) {
// ... Perform database query and
// ... Store the user object from the database in the req object
req.phone = phone;
return next();});
index.js
'use strict';
var express = require('express');
var router = express.Router();
var Utils = require("./JavaScript1");
/* GET home page. */
router.get('/', function (req, res) {
res.render('index', { title: 'Express' });});
router.get('/byPhone/:phone', function (req, res) {
var t = Utils.Phone(req.params.phone).then(value => { return value });
//At this point if i try to use await or consume by using web
//http://localhost:1337/byPhone/777777 i only get a promise ...
res.send(t);
});
module.exports = router;
JavaScript1.js
function sAdd(sPhone) {
return new Promise((resolve, reject) => { // (A)
setTimeout(() => resolve("01800" + sPhone), 5000); // (B)
});}
var utils = {
//at this point in the temp and temp2 variables only have promises
Phone:
async function (sPhone) {
var temp = await sAdd(sPhone).then(value => { return value });
var temp2 = await temp;
return temp2;
}
};
module.exports = utils;
I'm trying to consume it with the next Node Js Console App:
'use strict';
async function main()
{
console.log('Hello world');
var url = "http://localhost:1337/byPhone/777777";
request(url, function (err, response, body) {
if (err) { console.log(err); callback(true); return; }
var tt = body;
console.log(tt);
});
}
main();
i get the below answer:
(node:19492) UnhandledPromiseRejectionWarning: Unhandled promise
rejection (rejection id: 1): ReferenceError: request is not defined
I forgot to answer myself in this question, but I resolved what I wanted to do at that time this way:
I created a solution with 2 projects:
c# controllers webapp
on the c# side:
[Produces("application/json")]
[Route("test/Mondb")]
public class MondbController : Controller
{
// GET: api/Mondb
[HttpGet]
public string Get()
{
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("upixTest");
var collection = database.GetCollection<BsonDocument>("contacts");
var document = collection.Find(new BsonDocument()).ToList();
return document.ToJson(new JsonWriterSettings { OutputMode = JsonOutputMode.Strict });
}
// GET: api/Mondb/5
[HttpGet("{id}", Name = "Getmdb")]
public string Get(int id)
{
var filter = Builders<BsonDocument>.Filter.Eq("phone", id.ToString());
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("upixTest");
var collection = database.GetCollection<BsonDocument>("contacts");
var document = collection.Find(filter).FirstOrDefault();
return (document==null) ? "nothing":document.ToJson(new JsonWriterSettings { OutputMode = JsonOutputMode.Strict });
}
on the other side the node js project
functions.js
thefunctions = {
add: function (a, b) { return a + b; }, // test function
mongo: function () {
var axios = require('axios');
var tresult;
return axios.get('http://localhost:55384/test/Mondb/');
}
};
module.exports = thefunctions;
then in the server.js
'use strict';
var http = require('http');
var fs = require('fs');
var url = require('url');
var port = process.env.PORT || 1337;
var thefunctions = require("./thefunctions");
var dataToShow = "";
var JSON = require('JSON');
http.createServer(function (req, res) {
var hostname = req.headers.host;
var pathname = url.parse(req.url).pathname;
var fullurl = 'http://' + hostname + pathname;
var search = url.parse(req.url).search ? url.parse(req.url).search : "";
if (pathname === "/index.html") {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hi my friend\n');
var tout = thefunctions.mongo();
tout.then(function (response) {
res.write(JSON.stringify(response.data).toString());
res.write('\n');
res.end('\n\nThe End\n');
})
.catch(function (error) {
console.log(error);
res.write("error");
res.end('\n\nThe End\n');
});
}
else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.write('error my friend\n');
res.end('404 isnt available');
return;
}
}
).listen(port);
this way you will consume c# wb services from node js app

How to bind a helper stub to swagger-node with supertest?

I am using Swagger Node with express and I initialized the skeleton project. Swagger project create hello-world
Then inside the hello-world/api/controllers/hello_world.js I added a small modification to require a helper hello_helper.js and call its function helloHelper.getName().
'use strict';
let helloHelper = require('../helpers/hello_helper');
var util = require('util');
module.exports = {
hello: hello
};
function hello(req, res) {
var name = req.swagger.params.name.value || helloHelper.getName();
var hello = util.format('Hello, %s!', name);
res.json(hello);
}
hello-world/api/helpers/hello_helper.js
'use strict';
module.exports = {getName: getName};
function getName() {
return 'Ted';
}
I would like to stub helloHelper.getName() to return 'Bob' instead.
I can do so easily with:
hello-world/test/api/controllers/hello_world.js
// Create stub import of hello_helper
mockHelloHelper = proxyquire('../../../api/controllers/hello_world', { '../helpers/hello_helper': { getName: function () { return 'Bob'; } }
});
Using supertest how can I make swagger recognize my stub?
EDIT: Thanks to help from the answer below this solution worked for me.
var app, getNameStub, mockHelloHelper, request;
beforeEach(function (done) {
// Create stub import of hello_helper
mockHelloHelper = proxyquire('../../../api/controllers/hello_world', {
'../helpers/hello_helper': {
getName: function () {
return 'Bob';
}
}
});
app = require('../../../app');
request = supertest(app);
done();
});
...
it('should return a default string', function(done) {
request
.get('/hello')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.eql('Hello, Bob!');
done();
});
});
You need to initialize/require express app after you have proxyquired your dependency. Only then it can use your stubbed version of getName:
beforeEach(function () {
mockHelloHelper = proxyquire('../../../api/controllers/hello_world', {
'../helpers/hello_helper': {
getName: function () {
return 'Bob';
}
}
});
// initialize/require your app here
request = supertest(app);
});

node.js proxyquire stub asynchronous function from module required by another module

Module under test:
'use strict';
const config = require('config');
const q = require('q');
class RedisAccess {
static getValue(key) {
let deferred = q.defer();
if (config.redis.disableInteraction) {
deferred.resolve();
return deferred.promise;
}
config.redisClient.get(key, function handleResults(err, result) {
...
return deferred.promise;
}
}
exports = module.exports = RedisAccess;
Test:
var proxyquire = require('proxyquire').noPreserveCache();
var assert = require('assert');
var readdirError = new Error('some error');
var redisClientStub = { };
var calledBack;
// Override redisClient used by RedisAccess.js.
var redisClientProxy = proxyquire('../../../lib/data/redis/RedisAccess.js', { 'config' : redisClientStub });
// Test redisClient.get(...) to retrieve value given key using proxyquire for redisClient.
redisClientStub.redisClient.get = function (key, cb) {
cb(null, 'hello world');
};
calledBack = false;
// Test redisClient getValue async function.
redisClientProxy.getValue('some_key', function (err, value) {
assert.equal(err, null);
assert.equal('value', 'hello world');
callback = true;
});
The error when I execute the test is:
redisClientStub.redisClient.get = function (key, cb) {
^
TypeError: Cannot set property 'get' of undefined
How do I properly stub the config.redisClient.get(...) function?
I figured this out. I had to put a "stub within a stub" to stub the config.redisClient.get() function:
// Proxyquire allows unobstrusively overriding dependencies during testing.
// Override config used by RedisAccess.js.
var configStub = {
redisClient : {
createClient : function (port, address) {
// redis-mock-js used instead.
},
get : function (key, cb) {
if(key === 'test-rejected') {
cb(new Error('test-rejected'), 'rejected-promise');
}
else if(key === 'test-true') {
cb(null, true);
}
else if(key === 'test-get-valid') {
cb(null, 'valid-value');
}
else {
cb(new Error('Should not have gotten here!'), 'value');
}
},
}
};
which allowed me to construct this proxyquire:
var redisAccessProxy = proxyquire('lib/data/redis/RedisAccess.js', { 'config' : configStub });
and run this test using a proxy function for redisClient.get(...) which is called inside of RedisAccess.getValue(...):
var val = redisAccessProxy.getValue('test-get-valid');
assert.equal(val.isFulfilled(), true);
assert.equal(val.isRejected(), false);
assert.equal(val, 'valid-value');

Categories