I am new to nodejs and java script.
I am trying to read a config.json file in nodejs project using the below code snippet.whenever i run the program it's giving an error 'TypeError: Cannot set property 'getProjectSettings' of undefined'
Can some one help me to find the issue with the code?
var Env = "DEV"
function getConfigValue(configKey, subConfigKey, isblnEnvattr, callback) {
return callback(configKey, subConfigKey, isblnEnvattr);
}
function readConfigJson(configKey, subConfigKey, isblnEnvattr) {
if (Boolean(isblnEnvattr) == true) { //eg MONGODB_DEV
configKey = configKey + "_" + Env;
}
try {
return 'x';
} catch (err) {
return "key Not found";
}
}
module.export.getProjectSettings = function (configKey, subConfigKey, isblnEnvattr) {
return getConfigValue(configKey, subConfigKey, isblnEnvattr, readConfigJson)
}
getProjectSettings("Primary","secondary",false)
You have a typo - it should be module.exports, not module.export.
module.exports.getProjectSettings = function (configKey, subConfigKey, isblnEnvattr) {
return getConfigValue(configKey, subConfigKey, isblnEnvattr, readConfigJson)
}
Also, you can skip module before export, as long as you are not trying to export only one function (like such exports = function () { ... }).
exports.getProjectSettings = function (...) { ... }
Related
The bellow generates a file containing code and prints the output of the program:
class Code {
static list = require("./settings.json");
static fs = require("fs");
constructor(
code="print('Hello World')",//default code
lang = "py",//language
fn = "test",//file name
args = "" //arguments
) {
this.code = code;
const path = require('path');
this.fn = path.join(__dirname,fn) + "." + lang;//for platform independence
this.run_com = Code.replace(Code.list[lang], this.fn, args);
this._output="Server not responding";
this._error="Server not responding";
}
file_exists()
{
return Code.fs.existsSync(`${this.fn}`);
}
make_file() {
Code.fs.writeFile(`${this.fn}`, this.code, (err) => {
if (err) {
console.log(err);
}
});
}
run_file()
{
if(!this.file_exists())
this.make_file();
const { exec } = require("child_process");
exec(this.run_com, (error, stdout, stderr) =>{
if(error)
{
console.log(error);
}
else if(stderr==""){
this._output=stdout;
this._error="No error";
}
else{
this._error=stderr;
this._output=stdout;
}
console.log(this);//this
});
console.log(this);//this
}
get error()
{
return this._error;
}
get output()
{
return this._output;
}
static replace(
s //replace {}
) {
const arg = Object.values(arguments).slice(1); //convert obj to array removing s
for (let i in arg) {
s = s.replace("{}", arg[i]);
}
return s;
}
}
a = new Code("print('exd')");
a.run_file();
In the above program the output is:
The change in the state of object is not persistent once it comes out of the inner function.
why does the second console.log prints first and why the output of both the console.log are different, please justify in detail.
Also suggest a solution of this problem.
I think this is because exec is async and the second log is printed first. When the async code executes the second log is printed. And in the exec the values of _output and _error are changed hence the difference.
hey so I'm trying to const some JSON
const cidc = require('./cid/cid.json')
const dc = require('./details/cid.json')
const lc = require('./lik/cid.json')
if(!cidc){
return
}else{
fs.unlinkSync('./src/main/setting/cid/cid.json')
} if(!dc) {
return
}else {
fs.unlinkSync('./src/main/setting/details/cid.json')
} if (!lc){
return
}else {
fs.unlinkSync('./src/main/setting/lik/cid.json')
}
so I'm trying to delete the dc file and it error
how can I make if there is no such file named that it will do nothing (aka return nothing)
and if there is a file named that it will const it to a variable
Since require throws an error of Error: Cannot find module ... and you don't catch those errors, your script will fail.
You could define a new require-function where you catch the error and return undefined:
function safeRequire(path) {
try {
return require(path);
} catch(err) {
return undefined;
}
}
Then use this function in your script:
const cidc = safeRequire('./cid/cid.json')
const dc = safeRequire('./details/cid.json')
const lc = safeRequire('./lik/cid.json')
// rest of your code
Also you can simplify your if/else conditions by inverting the condition:
if (cidc) {
fs.unlinkSync('./src/main/setting/cid/cid.json')
}
if (dc) {
fs.unlinkSync('./src/main/setting/details/cid.json')
}
if (lc){
fs.unlinkSync('./src/main/setting/lik/cid.json')
}
Alternatively you don't even need to use require at all, just check if the files exist using e.g. fs.access(...).
You could directly use unlink with try catch without any requires
function unlink(filePath) {
try {
fs.unlinkSync(filePath);
} catch (e) {
//ignore
}
}
unlink('./src/main/setting/cid/cid.json')
unlink('./src/main/setting/details/cid.json')
unlink('./src/main/setting/lik/cid.json')
This is probably a noob JavaScript question, but I'm looking to know if my solution to a problem I am having is 'correct'
I have created the following sample application that recreates my error:
Firstly in index.js
var processor = require('./fileProcessor/processor.js');
var container = {
source: "source.txt",
destination: "destination.txt"
};
new processor().process(container);
I create my container object which has the name of the source file and the name of the destination file. This is passed into the process function of the processor:
var fileProcessor = require('./fileProcessor.js');
module.exports = function Processor() {
this.process = function(container) {
var file = new fileProcessor();
if(container.finished === undefined) {
if(container.body === undefined) {
file.read(container, this.process);
} else {
file.write(container, this.process);
}
}
};
};
As you can see this calls the read and write functions passing in the container and the process function as the callback, the fileProcessor looks like this:
var fs = require('fs');
module.exports = function() {
this.read = function(container, callback) {
fs.readFile(container.source, function (err, data) {
if(err) throw err;
container.body = data;
callback(container);
});
};
this.write = function(container, callback) {
fs.writeFile(container.destination, container.body, function(err) {
if(err) {
return console.log(err);
}
container.finished = true;
callback(container);
});
};
};
In simple terms the processor calls file.read, which reads the file and calls back into the process function, which then calls the write function. However at the end of the write function an error is thrown:
callback(container);
^
TypeError: object is not a function
Obviously when passing in this.process to file.write(container, this.process); the this isn't the this I intend it to be!
If I update my processor by adding a processFunction variable:
var fileProcessor = require('./fileProcessor.js');
module.exports = function Processor() {
var processFunction = function(container) {
var file = new fileProcessor();
if(container.finished === undefined) {
if(container.body === undefined) {
file.read(container, processFunction);
} else {
file.write(container, processFunction);
}
}
};
this.process = function(container) {
processFunction(container);
};
};
Everything works fine. Is this a good way to do this or is there a better solution?
I think this is a fine way to do it. There is one possible modification that you might make. Since you are creating a new name in your scope just for the purpose of recursing, you could just name your function and refer to it by its name inside of the function.
module.exports = function Processor() {
this.process = function processFunction(container) {
var file = new fileProcessor();
if(container.finished === undefined) {
if(container.body === undefined) {
file.read(container, processFunction);
} else {
file.write(container, processFunction);
}
}
};
};
Then you can avoid creating a name (processFunction) that will be visible outside the function.
Take a look here for reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function#Named_function_expression
I have a Node.js application that, upon initialisation, reads two tables from an SQL database and reconstructs their relationship in memory. They're used for synchronously looking up data that changes (very) infrequently.
Problem: Sometimes I can't access the data, even though the application reports successfully loading it.
Code:
constants.js
module.exports = {
ready: function () { return false; }
};
var log = sysLog('core', 'constants')
, Geo = require('../models/geo.js');
var _ready = false
, _countries = []
, _carriers = [];
function reload() {
_ready = false;
var index = Object.create(null);
return Geo.Country.find().map(function (country) {
var obj = country.toPlainObject()
, id = obj.id;
delete obj.id;
index[id] = obj;
return Object.freeze(obj);
}).then(function (countries) {
log.debug('Loaded ' + countries.length + ' countries');
_countries = countries;
return Geo.Carrier.Descriptor.find().map(function (carrier) {
var obj = carrier.toPlainObject();
if (obj.country) {
obj.country = index[obj.country];
}
return Object.freeze(obj);
}).then(function (carriers) {
log.debug('Loaded ' + carriers.length + ' carriers');
_carriers = carriers;
});
}).finally(function () {
_ready = true;
});
}
reload().catch(function (err) {
log.crit({ message: 'Could not load constants', reason: err });
process.exit(-42);
}).done();
module.exports = {
reload : reload,
ready : function () { return _ready; },
countries : function () { return _countries; },
carriers : function () { return _carriers; }
};
utils.js
var log = sysLog('core', 'utils')
, constants = require('./constants');
module.exports = {
getCountryByISO: function(iso) {
if (!iso) {
return;
}
if ('string' != typeof iso) {
throw new Error('getCountryByISO requires a string');
}
if (!constants.ready()) {
throw new UnavailableError('Try again in a few seconds');
}
switch (iso.length) {
case 2:
return _.findWhere(constants.countries(), { 'iso2' : iso.toUpperCase() });
case 3:
return _.findWhere(constants.countries(), { 'iso3' : iso.toUpperCase() });
default:
throw new Error('getCountryByISO requires a 2 or 3 letter ISO code');
}
},
getCarrierByCode: function(code) {
if (!code) {
return;
}
if ('string' != typeof code) {
throw new Error('getCarrierByCode requires a string');
}
if (!constants.ready()) {
throw new UnavailableError('Try again in a few seconds');
}
return _.findWhere(constants.carriers(), { 'code' : code });
},
getCarrierByHandle: function(handle) {
if (!handle) {
return;
}
if ('string' != typeof handle) {
throw new Error('getCarrierByHandle requires a string');
}
if (!constants.ready()) {
throw new UnavailableError('Try again in a few seconds');
}
return _.findWhere(constants.carriers(), { 'handle' : handle });
}
};
Use case
if (data.handle) {
carrier = utils.getCarrierByHandle(data.handle);
if (_.isEmpty(carrier)) {
throw new InternalError('Unknown carrier', { handle: data.handle });
}
}
What's going on: All errors are logged; as soon as I see an error (i.e. "Unknown carrier") in the logs, I check the SQL database to see if it should've been recognised. That has always been the case so far, so I check the debug log to see if data was loaded. I always see "Loaded X countries" and "Loaded Y carriers" with correct values and no sign of "Could not load constants" or any other kind of trouble.
This happens around 10% of the time I start the application and the problem persists (i.e. didn't seem to go away after 12+ hours) and seems to occur regardless of input, leading me to think that the data isn't referenced correctly.
Questions:
Is there something wrong in constants.js or am I doing something very obviously wrong? I've tried setting it up for cyclical loading (even though I am not aware of that happening in this case).
Why can't I (sometimes) access my data?
What can I do to figure out what's wrong?
Is there any way I can work around this? Is there anything else I could to achieve the desired behaviour? Hard-coding the data in constants.js is excluded.
Additional information:
constants.reload() is never actually called from outside of constants.js.
constants.js is required only in utils.js.
utils.js is required in app.js (application entry); all files required before it do not require it.
SQL access is done through an in-house library built on top of knex.js and bluebird; so far it's been very stable.
Versions:
Node.js v0.10.33
underscore 1.7.0
bluebird 2.3.11
knex 0.6.22
}).finally(function () {
_ready = true;
});
Code in a finally will always get called, regardless of if an error was thrown up the promise chain. Additionally, your reload().catch(/* ... */) clause will never be reached, because finally swallows the error.
Geo.Country.find() or Geo.Carrier.Descriptor.find() could throw an error, and _ready would still be set to true, and the problem of your countries and carriers not being set would persist.
This problem would not have occurred if you had designed your system without a ready call, as I described in my previous post. Hopefully this informs you that the issue here is really beyond finally swallowing a catch. The real issue is relying on side-effects; the modification of free variables results in brittle systems, especially when asynchrony is involved. I highly recommend against it.
Try this
var log = sysLog('core', 'constants');
var Geo = require('../models/geo.js');
var index;
var _countries;
var _carriers;
function reload() {
index = Object.create(null);
_countries = Geo.Country.find().map(function (country) {
var obj = country.toPlainObject();
var id = obj.id;
delete obj.id;
index[id] = obj;
return Object.freeze(obj);
});
_carriers = _countries.then(function(countries) {
return Geo.Carrier.Descriptor.find().map(function (carrier) {
var obj = carrier.toPlainObject();
if (obj.country) {
obj.country = index[obj.country];
}
return Object.freeze(obj);
});
});
return _carriers;
}
reload().done();
module.exports = {
reload : reload,
countries : function () { return _countries; },
carriers : function () { return _carriers; }
};
constants.reload() is never actually called from outside of
constants.js.
That's your issue. constants.reload() reads from a database, which is an aysnchronous process. Node's require() is a synchronous process. At the time constants.js is required in utils.js and the module.exports value is returned, your database query is still running. And at whatever point in time that app.js reaches the point where it calls a method from the utils module, that query could still be running, resulting in the error.
You could say that requiring utils.js has the side-effect of requiring constants.js, which has the side-effect of executing a database query, which has the side-effect of concurrently modifying the free variables _countries and _carriers.
Initialize _countries and _carriers as unresolved promises. Have reload() resolve them. Make the utils.js api async.
promises.js:
// ...
var Promise = require('bluebird');
var countriesResolve
, carriersResolve;
var _ready = false
, _countries = new Promise(function (resolve) {
countriesResolve = resolve;
})
, _carriers = new Promise(function (resolve) {
carriersResolve = resolve;
});
function reload() {
_ready = false;
var index = Object.create(null);
return Geo.Country.find().map(function (country) {
// ...
}).then(function (countries) {
log.debug('Loaded ' + countries.length + ' countries');
countriesResolve(countries);
return Geo.Carrier.Descriptor.find().map(function (carrier) {
// ...
}).then(function (carriers) {
log.debug('Loaded ' + carriers.length + ' carriers');
carriersResolve(carriers);
});
}).finally(function () {
_ready = true;
});
}
reload().catch(function (err) {
log.crit({ message: 'Could not load constants', reason: err });
process.exit(-42);
}).done();
module.exports = {
reload : reload,
ready : function () { return _ready; },
countries : function () { return _countries; },
carriers : function () { return _carriers; }
};
utils.js
getCarrierByHandle: function(handle) {
// ...
return constants.carriers().then(function (carriers) {
return _.findWhere(carriers, { 'handle' : handle });
});
}
Use case:
utils.getCarrierByHandle(data.handle).then(function (carrier) {
if (_.isEmpty(carrier)) {
throw new InternalError('Unknown carrier', { handle: data.handle });
}
}).then(function () {
// ... next step in application logic
});
This design will also eliminate the need for a ready method.
Alternatively, you could call constants.reload() on initialization and hang all possibly-dependent operations until it completes. This approach would also obsolete the ready method.
What can I do to figure out what's wrong?
You could have analyzed your logs and observed that "Loaded X countries" and "Loaded Y carriers" were sometimes written after "Unknown carrier", helping you realize that the success of utils.getCarrierByHandle() was a race condition.
I'm writing a JS terminal, and, for executing commands I use the following method:
function cmd(command){
var args = command.split(" ");
var size = args.filter(function(value) { return value !== undefined }).length;
if (args[0] === "command-name") {
...stuff to do
return;
}
if (args[0] === "another command") {
...stuff to do
return;
}
}
Is there some more efficient/neat way to do that?
You can use an object to store the command-name to function mapping, something akin to
var commands = {
"command-name": function doCommandName (args) {
alert("My arguments: " + args);
},
"another-command": function doAnotherCommand (args) {
}
};
function cmd(command) {
var args = command.split(" ");
var cmd = args[0];
if (commands.hasOwnProperty(cmd)) {
commands[cmd](args.slice(1));
}
else {
alert("Unknown command " + cmd);
}
};
I believe this can hardly be done in a more elegant way. However, you could use an array of objects, each of which would have a string name and some function execute as members, and the implementation would select the array member based on args[0].