Node.JS reading json file isn't displaying new file updates - javascript

I have two configuration files (log.txt, and config.json) that are updated after each computation and the next computation is dependent on the results of the previous computation which are stored in the two files.
The problem is, when I read the json files during computation I only get the results of the initial first computation. The new updates are not reflected in the new file reads. But when I check the files, both have been updated.
What could be the problem?
Thanks in advance.
Script for Reading the configuration files (pFunctions.js):
const fs = require('fs');
// Read logs
function readLog() {
try {
return fs.readFileSync(__dirname + '/' + 'log.txt', {'encoding':'utf8','flag':'rs+'});
}
catch (err) {
return '';
}
}
// Read configurations
function readConfig() {
try {
return fs.readFileSync(__dirname + '/' + 'config.json', {'encoding':'utf8','flag':'rs+'});
}
catch (err) {
return '';
}
}
// Function to read dataset
function readDataset() {
....
....
}
// Read data from configuration files
let config = readConfig(); // config.json
let log = readLog(); // log.txt
// Parse data to JSON
let cfg = JSON.parse(config);
let lcg = JSON.parse(log);
....
....
// Fetch dataset based on the configuration and log file
let dataset = readDataset();
// Create parameter function
const pFunctions = {
parameter1: dataset // set dataset as value of parameter1
}
// Export function as JSON Object
module.exports={pFunctions};
I then import the object in the computation.js script like this:
const {pFunctions} = require('./app/config/pFunctions');
// Capture new 'uParams' computing parameters
let newParams = pFunctions;

Related

How can we store the instance of a couple of variables once computed forever?

Right now, I have to precompute the floyd warshall cost and path matrix every time my server loads.
This is for a map which is N by N. We only have a couple of maps so I think I should precompute into variables before the server even starts up.
I have 4 variables.
Cost -> Matrix of values.
Path -> Matrix of tuples
TupleVal -> Tuple as a key mapped to a number (Map() object in JS)
IndexVal -> Number as a key mapped to a Tuple (Map() object in JS)'
How can I compute these 4 variables ONCE, and store it somewhere such that it is relatively
easy to retrieve? Should this be done through JSON? If so how can I write to a JSON file and read from a JSON file these specific datastructures?
//This is the map I use. A Tuple is converted to a string which maps to number
class ArrayKeyedMap extends Map {
get(array) {
return super.get(this.toKey(array));
}
set(array, value) {
return super.set(this.toKey(array), value);
}
has(array) {
return super.has(this.toKey(array));
}
delete(array) {
return super.delete(this.toKey(array));
}
toKey(array) {
return JSON.stringify(array);
}
}
.
.
.
// This is what I return ForbiddenVals and tupleVal are arraykeyedmap object
// index is a map object, mapping a number to a tuple. (x,y)
// path and cost are a 2 dimensional array, which contains numbers.
return [path, cost, tupleVal, index, ForbiddenVals]
Above, is basically the data structures I use. What is the easiest way to compute these values ONCE, so I never have to ever again unless I make a change to the maps?
Thank you
If you're using Express you can save the JSON to a file with fs
const fs = require('fs');
const path = require('path');
//resolve a relative path to an absolute one
const cacheDir = path.resolve('./json');
//the name of the json file, can be anything in any directory
const jsonFile = `${cacheDir}/json/n_x_n.map.json`;
let data;
//create the cache directories if they don't exist
if(!fs.existsSync(`${cacheDir}/json`)) {
fs.mkdirSync(`${cacheDir}/json`, {recursive: true});
}
//if the JSON file does not exist, generate the json and save it to the disk
if(!fs.existsSync(jsonFile)) {
data = genData(); //this is where you generate hte values once
fs.writeFile(jsonFile, JSON.stringify(data), (err) => {
if(err) {
console.error('Couldn\'t save JSON', err);
} else {
console.log('Saved JSON');
}
}
} else {
//otherwise load the JSON from the file
data = JSON.parse(fs.readFileSync(jsonFile));
}
//do whatever with the data
If it is just a website you could use localstorage
//load the data from localStorage
let data = localStorage.getItem('json');
//if there is no data in the localStorage, generate the data and save it
if(!data) {
data = genData();
localStorage.setItem('json', data);
}
//do whatever with the data

At an object's instantiation time how does one handle best the asynchronous initialization of one of its properties?

I've never created a Javascript module/library before so this is a bit new to me so apologizes for my lack of knowing what to google.
I'm creating a library that will hold information from a URL that is provided by a user. I want to parse the URL's path (the part that comes after the domain) as well as retain a header value that's provided by the URL's response.
It's basic but here's what I have so far:
function Link(someURL) {
this.url = someURL;
this.urlPath = "";
this.uuid = "";
this.getPath = function (someURL) {
// do regexp parsing and return everything after the domain
};
this.getUUID = function (someURL) {
// fetch the URL and return what is in the response's "uuid" header
}
}
Ideally, I'd the module to automatically get all the information upon construction:
var foo = new Link("http://httpbin.org/response-headers?uuid=36d09ff2-4b27-411a-9155-e82210a100c3")
console.log(foo.urlPath); // should return "uuid"
console.log(foo.uuid); // should return the contents in the "uuid" header in the response
How do I ensure the this.urlPath and this.uuid properties get initialized along with this.url? Ideally, I'd only fetch the URL once (to prevent rate limiting by the target server).
After a lot of trial and error, I ended up doing something more like this:
class Link {
constructor (url_in) {
const re = RegExp("^https://somedomain.com\/(.*)$");
this.url = re[0];
this.linkPath = re[1];
}
async getUUID() {
const res = await fetch("https://fakedomain.com/getUUID?secret=" + this.linkPath);
this.uuid = res.uuid;
}
async getJSON() {
const res = await fetch("https://fakedomain.com/getJSON?uuid=" + this.uuid);
this.json = await res.json();
}
async initialize() {
await this.getUUID();
await this.getJSON();
}
}
const someLinkData = new Link("https://reallydumbdomain.com/2020/10/4/blog");
someLinkData.initialize()
.then(function() {
console.log(this.json); // this now works
});
I think a future iteration of this will require me to send a promise with the initialize function but for now, this works.

Async and Sync Functions Node JS

I have a couple of functions I am running to download a zip file from Nexus, then unzip/extract the contents of the zip file, finally a search for a specific file type. All function work, however the synchronous search for some reason is not producing any results. If I simply run the download and extract functions in 1 script, then execute the search in another script I get my expected results. I am almost positive it is due to the search being synchronous whereas the download and extract are both async. Is there a quick way to add the find function at the end after the download & extract functions have run? Below is the code:
//npm modules
const fs = require('fs-extra');
const download = require('download');
const unzipper = require('unzipper');
const path = require('path');
//Custom Variables
const artifact = 'SOME_FILE.zip';
const repo = "SOME NEXUS REPOSITORY";
const url = "http://SOME URL/repository/";
const directory = 'SOME DIRECTORY';
//Get Artifact and Extract it to local directory function
const getArtifact = async () => {
const getArtifact = await download(url+repo, "./unzip")
const file = await fs.writeFileSync(directory+artifact, await download(url+repo))
const readStream = await fs.createReadStream(directory + artifact).pipe(unzipper.Extract({path:
directory}))
}
//Find function which should run after download and extract have been fulfilled
const findFile = function (dir, pattern) {
var results = [];
fs.readdirSync(dir).forEach(function (dirInner) {
dirInner = path.resolve(dir, dirInner);
var stat = fs.statSync(dirInner);
console.log(stat)
if (stat.isDirectory()) {
results = results.concat(findFile(dirInner, pattern));
}
if (stat.isFile() && dirInner.endsWith(pattern)) {
results.push(dirInner);
}
});
console.log(results)
return results;
};
//clear contents of directory before new download and extract
fs.emptyDirSync(directory)
//call download and extract function
getArtifact()
When I run "findFile" after the download & extract by itself in a separate script I get expected array output. However, when I try to incorporate (see below) this into the same script I get the an empty array:
getArtifact().then(function findFile (dir, pattern) {
var results = [];
fs.readdirSync(directory).forEach(function (dirInner) {
dirInner = path.resolve(directory, dirInner);
var stat = fs.statSync(dirInner);
console.log(stat)
if (stat.isDirectory()) {
results = results.concat(findFile(dirInner, pattern))
if (stat.isFile() && dirInner.endsWith(pattern)) {
results.push(dirInner);
}
}
console.log(results)
return results;
})
})
//Output
[]
//If I try the following:
getArtifact().then(findFile(directory, file))
// I get same empty array
[]
//If I run "findFile" in its own script after the download extract I get the following:
[
'SOME_FILE_PATH\\document1',
'SOME_FILE_PATH\\document2',
'SOME_FILE_PATH\\document3',
'SOME_FILE_PATH\\document4',
'SOME_FILE_PATH\\document5',
'SOME_FILE_PATH\\document6',
'SOME_FILE_PATH\\document7
]
Any help with how I can incorporate my findFile function into my existing download&extract function is appreciated...

How to read the zip file contents in react application using jszip preferably

I have a requirement to read the zip file contents , This is how the zip folder will look like Manifest.zip , The files in the Manifest.zip are outline.png, publish.png, manifest.json. I need to read the manifest.json(key value pairs) on the fly in a react application.
Basically requirement is when user clicks on "maifest" link a pop up needs to shown which show manifest.json contents in the UI react components.
I tried using JSZip library, and the code is as below
var zip = new JSZip();
zip.loadAsync("Manifest.zip")
.then(function (zip) {
console.log(zip.files);
// Expected outline.png, publish.png, manifest.json
});
I get the error as shown below?
Don't know what the error is about, have you tried another zip file?
Anyway, here is my tsx code with reactjs hooks:
const [files, setFiles] = useState<File[]>(undefined);
const [fileInfo, setFileInfo] = useState<IFileInfo>(undefined);
useEffect(() => {
if (files) {
const f = files[0];
const dateBefore = new Date();
JSZip.loadAsync(f) // 1) read the Blob
.then((zip) => {
const contents = [];
zip.forEach((relativePath, zipEntry) => { // 2) print entries
contents.push(zipEntry.name);
});
const loadTime = moment(new Date()).diff(moment(dateBefore));
setFileInfo({
loadTime,
contents: contents.sort(),
error: null
});
}, (e) => {
const loadTime = moment(new Date()).diff(moment(dateBefore));
setFileInfo({
loadTime,
contents: [],
error: "Error reading " + f.name + ": " + e.message
});
});
}
}, [files]);
// below some code that adds a file to files with drag and drop interface
Take a look at this library. Seems stable and easy to use.
var AdmZip = require('adm-zip');
// reading archives
var zip = new AdmZip("./my_file.zip");
var zipEntries = zip.getEntries(); // an array of ZipEntry records
zipEntries.forEach(function(zipEntry) {
console.log(zipEntry.toString()); // outputs zip entries information
});

Return a Variable from a class function without Undefinided Reference NodeJS

Every time I try to assign a variable from a class I cannot use it.
Then when I make a small sample code to put on-line, the functions work in the small example. How do I log a variable to the screen after returning it from a class?
In the small code examples it works, in the larger code to actually do things, I receive an undefined reference error probably as the functions take longer to run.
With a main.js like:
var KeyPair = require('./Keypair');
var Q = require("q");
path_k = __dirname + "/user_p_key_1.txt";
var pair = new KeyPair();
var p = pair.getPublicKey(path_k);
console.log(p + " sig_1"); // error: logs "undefined sig_1" instead of key.
Q.fcall(p = pair.getPublicKey(path_k))
.then(console.log(p + " sig_2")); // error: logs "undefined sig_2" instead of key.
The output is:
undefined sig_1
undefined sig_2
Key fileread successfully
Is it a valid public key?
true
Key:GAVAPNTBWRG337JWZYLR2SBPD5KFA2PPXDMN4HEEBLWSZQIKTPOEFZL6
Key fileread successfully
Is it a valid public key?
true
Key:GAVAPNTBWRG337JWZYLR2SBPD5KFA2PPXDMN4HEEBLWSZQIKTPOEFZL6
Key fileread successfully
Is it a valid public key?
true
Key:GAVAPNTBWRG337JWZYLR2SBPD5KFA2PPXDMN4HEEBLWSZQIKTPOEFZL6
Using the Keypair.js Class:
var fs = require('fs');
var StellarBase = require('stellar-base');
var StellarSdk = require('stellar-sdk');
// A class for referencing KeyPair methods to read and write from files
var method = KeyPair.prototype;
function KeyPair() {
}
method.getPublicKey = function(path_k) {
// Read PublicKey from filename
fs.open(path_k, 'r', function(err, fd) {
if (err) {
throw 'could not open file: ' + err;
}
// Buffer Array Initialised for the Public Key
// write the contents of the buffer, from position 0 to the end, to the file descriptor returned in opening our file
var arr = [null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null];
var buffer_k = Buffer.from(arr);
fs.read(fd, buffer_k, 0, buffer_k.length, null, function(err) {
if (err) throw 'error reading file: ' + err;
fs.close(fd, function() {
//console.log('Key fileread successfully');
var user_encoded_k = StellarBase.StrKey.encodeEd25519PublicKey(buffer_k);
//console.log('Is it a valid public key?');
//console.log(StellarBase.StrKey.isValidEd25519PublicKey(user_encoded_k));
//console.log('Key:' + user_encoded_k);
return user_encoded_k
});
});
});
};
Reading in a Public Key "user_p_key_1.txt":
*¶a´M½ý6ÎH/TPiï¸ØÞ„
í,Á
݆B
The key is a for a test-server.
Also, I created the simplified Keypair.js as below to show that my code isn't working, and the sample Keypair.js worked different to the Keypair.js above and assign the variable and logged it to screen correctly.
Simplified Keypair.js
var fs = require('fs');
// A class for referencing KeyPair methods to read and write from files
var method = KeyPair.prototype;
function KeyPair() {
}
method.getPublicKey = function(value) {
return 1
};
module.exports = KeyPair;
I considered it was perhaps something to do with the asynchronous interpreter not being finished with the function when the variable is called so I implemented it afterwards in promises, and to my disbelief p still returned undefined. How do we assign a variable from a class functions and use it in Node.JS?

Categories

Resources