Accessing variables from my index.js in another file - node.js

I am trying to make a bit of code execute as if it was in the index.js of my nodejs app.
I have the following code:
index.js
var data = [];
function populateData(){
for(var i = 0; i < 100; i++){
data.push(i);
}
}
populateData();
require('./other.js')();
other.js
module.exports = function(){
console.log(data);
}
However, this tells me data is not defined. Is there any way to read the data variable like this?
I tried
require('./other.js').apply(null);
and
require('./other.js').apply(this);
However neither worked for me

Use another module for common variable.
common.js
module.exports = {
data: []
}
index.js
const common = require('./common');
const other = require('./other');
function populateData(){
for(var i = 0; i < 100; i++){
common.data.push(i);
}
}
populateData();
other.test();
other.js
const common = require("./common");
module.exports = {
test: function(){
console.log(common.data);
}
}

You can pass the data to the file like this
index.js
var data = [];
function populateData() {
for (var i = 0; i < 100; i++) {
data.push(i);
}
}
populateData();
require('./other.js')(data);
other.js
module.exports = function(data) {
console.log(data);
};

Related

Error [ERR_REQUIRE_ESM]: require() of ES Module ...\angular\node_modules\globby\index.js from ...\angular\gulpfile.js not supported

My angular project was perfectly run but for some error I tried to reinstall Nodejs and npm and problems began. After that when I try to use command npm start in my angular project I faced this error:
Error [ERR_REQUIRE_ESM]: require() of ES Module D:...\angular\node_modules\globby\index.js from D:...\angular\gulpfile.js not supported.
Instead change the require of index.js in D:...\angular\gulpfile.js to a dynamic import() which is available in all CommonJS modules.
at Object. (D:...\angular\gulpfile.js:4:14)
at async Promise.all (index 0) {
code: 'ERR_REQUIRE_ESM'
}
I didn't know if this reinstalling was my source of problem so I tried to move to my old version of Nodejs and npm but problem is still there.
current version of Nodejs and npm on my system:
D:\...\angular>node -v
v17.7.0
D:\...\angular>npm -v
7.19.1
I've read lots of same questions but answers didn't work for me.
for example I tried to use this solution on my gulpfile.js
And here is my gulpfile.js file:
var gulp = require("gulp");
var path = require('path');
var merge = require("merge-stream");
var globby = require('globby');
var concat = require('gulp-concat');
var less = require('gulp-less');
var uglify = require('gulp-uglify');
var cleanCss = require('gulp-clean-css');
var bundleConfig = require(path.resolve(__dirname, 'bundles.json'));
var production = false;
var styleEntries = {};
var scriptEntries = {};
function processInputDefinition(input) {
var result = [];
for (var i = 0; i < input.length; i++) {
var url = input[i];
if (url.startsWith('!')) {
result.push('!' + path.resolve(__dirname, url.substring(1)));
} else {
result.push(path.resolve(__dirname, url));
}
}
return result;
}
function fillScriptBundles() {
// User defined bundles
for (var k = 0; k < bundleConfig.scripts.length; k++) {
var scriptBundle = bundleConfig.scripts[k];
scriptEntries[scriptBundle.output] = globby.sync(processInputDefinition(scriptBundle.input), {
noext: true
});
}
}
function fillStyleBundles() {
// User defined styles
for (var k = 0; k < bundleConfig.styles.length; k++) {
var styleBundle = bundleConfig.styles[k];
styleEntries[styleBundle.output] = globby.sync(processInputDefinition(styleBundle.input), {
noext: true
});
}
}
function getFileNameFromPath(path) {
return path.substring(path.lastIndexOf('/') + 1);
}
function getPathWithoutFileNameFromPath(path) {
return path.substring(0, path.lastIndexOf('/'));
}
function createScriptBundles() {
var tasks = [];
for (var script in scriptEntries) {
tasks.push(
createScriptBundle(script)
);
}
return tasks;
}
function createScriptBundle(script) {
var bundleName = getFileNameFromPath(script);
var bundlePath = getPathWithoutFileNameFromPath(script);
var stream = gulp.src(scriptEntries[script]);
if (production) {
stream = stream
.pipe(uglify());
}
return stream.pipe(concat(bundleName))
.pipe(gulp.dest(bundlePath));
}
function createStyleBundles() {
var tasks = [];
for (var style in styleEntries) {
tasks.push(
createStyleBundle(style)
);
}
return tasks;
}
function createStyleBundle(style) {
var bundleName = getFileNameFromPath(style);
var bundlePath = getPathWithoutFileNameFromPath(style);
var stream = gulp.src(styleEntries[style])
.pipe(less({
math: 'parens-division'
}));
if (production) {
stream = stream.pipe(cleanCss());
}
return stream
.pipe(concat(bundleName))
.pipe(gulp.dest(bundlePath));
}
function build() {
production = true;
fillScriptBundles();
fillStyleBundles();
var scriptTasks = createScriptBundles();
var styleTasks = createStyleBundles();
return merge(scriptTasks.concat(styleTasks));
}
function buildDev() {
fillScriptBundles();
fillStyleBundles();
var scriptTasks = createScriptBundles();
var styleTasks = createStyleBundles();
console.log("Dynamic bundles are being created.");
return merge(scriptTasks.concat(styleTasks));
}
exports.build = build;
exports.buildDev = buildDev;

making node wait for db call to get completed

I just started writing node.js code.
I'm writing a code that extracts data from a pdf file, cleans it up and stores it in a database (using couchdb and accessing that using nano library).
The problem is that the calls are being made asynchronously... so the database get calls (i make some get calls to get a few affiliation files during the clean up) get completed only after the program runs resulting in variables being undefined. is there any way around this?
I've reproduced my code below
const fs = require('fs');
const os = require('os');
var couchDB = require('couch-db').CouchDB;
var pdf_table_extractor = require('pdf-table-extractor');
const filename = "PQ-PRI-0005-1806-01-0000_quoteSlipForLIBVIDGI1.pdf"
var nano = require('nano')('https://couchadmin:difficulttoguessmypassword#dbdev.perilwise.com');
var server = new couchDB('https://db.url.com');
server.auth("admin","admin");
var db = nano.db.use('pwfb');
var temp = [];
//New callView function
async function callView(){
try{
const doc = await view('liabilitymdm','pi');
for (var i =0; i<doc.rows.length;i++){
tmp.push(doc.rows[i]);
};
return doc;
} catch(e){
console.log(e);
};
};
function suc(result){
let ttmp = [];
console.log(result);
var pageTables = result.pageTables;
var firstPageTables = pageTables[0].tables;
ttmp = callView();
//this console log shows Promise { <pending> }
console.log(ttmp)
for (var k = 0; k < firstPageTables.length; k++) {
var temp = firstPageTables[k];
if (temp.length > 0) {
dump.push(temp);
}
}
// console.log(dump);
var insurer = filename.substr(37,8);
read_quote_slip(insurer,dump);
}
var read_quote_slip = (insurer,data) => {
console.log("read_quote_slip correctly entered");
var finOut = {};
if (insurer === "LIBVIDGI"){
finOut.insurer = insurer;
finOut.policyType = data[2][0].replace(/Quotation for/g,"");
finOut.natureOfWork = data[13][3];
let dedpos = indexGetter(data, "Deductible")[0];
finOut.deductible = data[dedpos+1][0];
let cov = indexGetter(data, "Coverage Territory and Jurisdiction")[0];
finOut.coverageTerritory = data[cov+1][0].replace(/Territory/g,"");
finOut.coverageJurisdiction = data[cov+2][0].replace(/Jurisdiction/g,"");
let ext = indexGetter(data,"Extensions")[0];
finOut.coverage = data[ext+1][0].split(/\r?\n/);
let majexc = indexGetter(data,"Major Exclusions")[0];
finOut.exclusions = data[majexc+1][0].split(/\r?\n/);
let prdtl = indexGetter(data,"Description")[0];
let prm = premiumcompute(data,prdtl,dedpos);
finOut.premium = prm;
finCleaned = libvidgi_cleaned(finOut);
// console.log(finCleaned);
}
}
var indexGetter = (words,toFind) => {
var finindex = [];
for (var i = 0; i < words.length; i++){
for (var j = 0; j < words[i].length; j++){
if(words[i][j].indexOf(toFind) >=0 ){
finindex.push(i);
}
}
}
return finindex;
}
var premiumcompute = (data, from, to) => {
let finprem = [];
let numbop = to - from - 2;
let incr = 0;
for (var i = from+2; i < to; i++){
let pr = {};
pr.option = incr+1;
pr.sumInsured = data[i][2].replace(/ /g,"");
pr.premium = data[i][data[i].length - 1].replace(/ /g,"");
finprem.push(pr);
incr +=1;
}
return finprem;
}
var libvidgi_cleaned = (finOut) => {
return finOut;
}
var fal = (result) => {
console.log(result);
console.log("there was an error");
}
var readPDFFile = function(filename){
//Decide which insurer from the filename
// console.log(filename);
console.log(filename.substr(37,8)+"Printed on line 38");
insurer = filename.substr(37,8)
pdf_table_extractor(filename, (result) => {suc(result)} , fal);
}
var libvidgi_data_extract = (data) => {
console.log(data);
let arr = data.pageTables.tables;
for (var i = 0; i <= arr.length; i++ ){
console.log(arr[i]);
}
}
readPDFFile(filename);
This answer assumes you are using Node.js > v7.6
Since db.view accepts a callback, and you wish to wait for it to finish, one solution will be to promisify it - meaning to turn it into a promise which can be awaited. You can use a library like Bluebird or you can even use Node's builtin promisify util. Then you can rewrite callViews:
const {promisify} = require('util');
const view = promisify(db.view);
async function callView() {
try {
const doc = await view('liabilitymdm', 'pi');
// the async operation is now guaranteed to be done
// (if there is an error it will be caught by the catch clause)
for (var i = 0; i < doc.rows.length; i++) {
temp.push(doc.rows[i]);
}
console.log(temp);
} catch (e) {
}
}
If you are not using Node.js > v7.6 (and cannot use async\await you can still utilize promises, by using their then method:
const {promisify} = require('util');
const view = promisify(db.view);
function callView() {
view('liabilitymdm', 'pi')
.then(doc => {
for (var i = 0; i < doc.rows.length; i++) {
temp.push(doc.rows[i]);
}
console.log(temp);
return temp;
})
.then(temp => {
console.log(temp);
})
.catch(e => {});
}
Notice how the first then is returning something which is used in a later then.
To make Node run asynchronously, you can use the keywords async and await.
They work like this:
async function doSomething () {
const formattedData = formatData();
const result = await db.postToDatabase(formattedData);
// the below will not happen until the above line is finished
doSomethingElse(result);
}
It's pretty simple in Node to get functions to execute asynchronously. Just put the async keyword at the beginning of the function definition and then put await in front of anything that you want to block execution until completed.

how to include node.js modules with following pattern

a.js
if(typeof(MAIN) == "undefined") var MAIN = {};
(function(_e) {
function SLfunction(yea,mx,dx){
var out = "abc";
return(out)
}
_e.SLfunction = function(yea,mx,dx) {
return SLfunction(yea,mx,dx);
};
}(MAIN));
b.js
if(typeof(MAIN) == "undefined") var MAIN = {};
(function(_e) {
function SLfunction2(yea,mx,dx){
var out = "def";
return(out)
}
_e.SLfunction2 = function(yea,mx,dx) {
return SLfunction2(yea,mx,dx);
};
}(MAIN));
main.js
var MAIN =(a.js)
var MAIN =(b.js)
How to include the modules into main.js so both SLfunction and SLfunction2 able to use. Thanks

Ember blueprint that injects environment config?

I'm relatively new to Ember and was wondering if there is a way to create a blueprint/generator that would inject a new value into the environment config while maintaining all existing configuration. Is there some Ember magic that allows an existing file to act as the blueprint template? My ideal implementation would look something like this:
ember g platform foo
// config/environment.js
module.exports = function(environment) {
var ENV = {
// Existing config values here...
APP: {
platforms: {
foo: 'abc123' // Generator injects the 'foo' platform and a GUID
}
};
// Existing environment-specific settings here...
return ENV;
};
Is this something that would be more easily accomplished using Node's fs.readFile() and fs.writeFile()? If so, how could I parse environment.js?
No there's no existing magic in Ember to my knowledge sorry. When you generate a route, something very similar to what you are talking about happens but the code is rather complex. The ember generate route new_route function has a call to this function
function addRouteToRouter(name, options) {
var routerPath = path.join(options.root, 'app', 'router.js');
var source = fs.readFileSync(routerPath, 'utf-8');
var routes = new EmberRouterGenerator(source);
var newRoutes = routes.add(name, options);
fs.writeFileSync(routerPath, newRoutes.code());
}
which then exectutes interpreter level like code to add the router and revert it back to code:
module.exports = EmberRouterGenerator;
var recast = require('recast');
var traverse = require('es-simpler-traverser');
var Scope = require('./scope');
var DefineCallExpression = require('./visitors/define-call-expression.js');
var findFunctionExpression = require('./helpers/find-function-expression');
var hasRoute = require('./helpers/has-route');
var newFunctionExpression = require('./helpers/new-function-expression');
var resourceNode = require('./helpers/resource-node');
var routeNode = require('./helpers/route-node');
function EmberRouterGenerator(source, ast) {
this.source = source;
this.ast = ast;
this.mapNode = null;
this.scope = new Scope();
this.visitors = {
CallExpression: new DefineCallExpression(this.scope, this)
};
this._ast();
this._walk();
}
EmberRouterGenerator.prototype.clone = function() {
var route = new EmberRouterGenerator(this.source);
return route;
};
EmberRouterGenerator.prototype._ast = function() {
this.ast = this.ast || recast.parse(this.source);
};
EmberRouterGenerator.prototype._walk = function() {
var scope = this.scope;
var visitors = this.visitors;
traverse(this.ast, {
exit: function(node) {
var visitor = visitors[node.type];
if (visitor && typeof visitor.exit === 'function') {
visitor.exit(node);
}
},
enter: function(node) {
var visitor = visitors[node.type];
if (visitor && typeof visitor.enter === 'function') {
visitor.enter(node);
}
}
});
};
EmberRouterGenerator.prototype.add = function(routeName, options) {
if (typeof this.mapNode === 'undefined') {
throw new Error('Source doesn\'t include Ember.map');
}
var route = this.clone();
var routes = route.mapNode.arguments[0].body.body;
route._add.call(
route,
routeName.split('/'),
routes,
options
);
return route;
};
EmberRouterGenerator.prototype._add = function(nameParts, routes, options) {
options = options || {};
var parent = nameParts[0];
var name = parent;
var children = nameParts.slice(1);
var route = hasRoute(parent, routes);
if (!route) {
if (options.type === 'resource') {
route = resourceNode(name, options);
routes.push(route);
} else {
route = routeNode(name, options);
routes.push(route);
}
}
if (children.length > 0) {
var routesFunction = findFunctionExpression(route.expression.arguments);
if (!routesFunction) {
routesFunction = newFunctionExpression();
route.expression.arguments.push(routesFunction);
}
this._add(children, routesFunction.body.body, options);
}
};
EmberRouterGenerator.prototype.remove = function(routeName) {
if (typeof this.mapNode === 'undefined') {
throw new Error('Source doesn\'t include Ember.map');
}
var route = this.clone();
var routes = route.mapNode.arguments[0].body.body;
var newRoutes = route._remove.call(
route,
routeName.split('/'),
routes
);
if (newRoutes) {
route.mapNode.arguments[0].body.body = newRoutes;
}
return route;
};
EmberRouterGenerator.prototype._remove = function(nameParts, routes) {
var parent = nameParts[0];
var name = parent;
var children = nameParts.slice(1);
var route = hasRoute(parent, routes);
var newRoutes;
if (children.length > 0) {
var routesFunction = route.expression && findFunctionExpression(route.expression.arguments);
if (routesFunction) {
newRoutes = this._remove(children, routesFunction.body.body);
if (newRoutes) {
routesFunction.body.body = newRoutes;
}
return routes;
}
} else {
if (route) {
routes = routes.filter(function(node) {
return node !== route;
});
return routes;
} else {
return false;
}
}
};
EmberRouterGenerator.prototype.code = function(options) {
options = options || { tabWidth: 2, quote: 'single' };
return recast.print(this.ast, options).code;
};
So then there's the alternative, which involves reading the file, adding in your new environment in the correct place after parsing the file correctly, and then writing the stream back. The complexity of what you are wanting to do probably outweighs the time it would take to do this manually IMO. If this is something you are doing often, maybe consider writing a script in another language that's better(read as more people use it for this) at textual file manipulation

For-loop and async callback in node.js?

I'm new to JavaScript and to node.js. I want to loop through a directory and add all file stat (not other directories) to an array. As you see below there is a problem with my code since the callback will probably get called after the for loop has finished so using the "i"-variable in the callback method will not work. But how should the code look so that the below snippet works? Does it have something to do with closures?
Thanks for help!
fs.readdir(SYNCDIR, function(err1, files) {
var filesOnly = [];
if(!err1) {
for(var i = 0; i < files.length; i++) {
var imgFilePath = SYNCDIR + '/' + files[i];
fs.stat(imgFilePath, function(stat){
if (stat.isFile()){
filesOnly[i] = stat; // This will not be correct since the for-loop has finished
}
});
}
}
});
You are right about needing to use a closure. You should wrap the contents of the for loop in a self-invoking function to preserve the value of i for each iteration.
fs.readdir(SYNCDIR, function(err1, files) {
var filesOnly = [];
if(!err1) {
for(var i = 0; i < files.length; i++) {
(function(i) {
var imgFilePath = SYNCDIR + '/' + files[i];
fs.stat(imgFilePath, function(stat){
if (stat.isFile()){
filesOnly[i] = stat;
}
});
})(i);
}
}
});
One way is to rewrite the innards of the loop to use a closure:
fs.readdir(SYNCDIR, function(err1, files) {
var filesOnly = [];
if(!err1) {
for(var i = 0; i < files.length; i++) {
(function(index) {
var imgFilePath = SYNCDIR + '/' + files[index];
fs.stat(imgFilePath, function(stat){
if (stat.isFile()){
filesOnly[index] = stat;
}
});
})(i);
}
}
});
A better looking example, achieving the same, using Array.prototype.forEach:
fs.readdir(SYNCDIR, function(err1, files) {
var filesOnly = [];
if(!err1) {
files.forEach(function(file, i) {
var imgFilePath = SYNCDIR + '/' + file;
fs.stat(imgFilePath, function(stat){
if (stat.isFile()){
filesOnly[i] = stat;
}
});
});
}
});
Alternatively use the new threads module ( https://github.com/robtweed/Q-Oper8 ) and then you can do all this stuff much more simply using standard synchronous coding within the threads child processes, since they only deal with one user's request at a time.
Goodbye to async logic and nested callbacks!

Resources