class Main {
constructor() {
this.argument = process.argv.splice(2);
this.fileToCopy = this.argument[0];
this.destination = this.argument[1] ? this.argument[1] : '';
this.callAdress = process.cwd();
this.finalAdress = `${this.callAdress}\\` + this.destination;
//Problematic Part
if(this.fileExists(this.fileToCopy, this.finalAdress)) console.log("EXISTS")
else console.log("DOESNT EXISTS");
}
async fileExists(file, path) {
try {
let files = await fs.readdir(path);
return files.includes(file);
} catch(e) {
console.log("ERROR", e)
return false;
}
}
}
im trying to check if file exists in directroy, using promises for fs,the problematic part always returns true. im out of ideas.
You call if (this.fileExists...) which is equivalent to if (true) because this.fileExists always return a Promise, which would be implicitly coerced to boolean value of true
So you should call fileExists with await instead, and wrap this call in an IIFE function
And remember to put a semicolon at the beginning of IIFE function to avoid concatnating with the previous line (this.destination(async...))
class Main {
constructor() {
this.argument = process.argv.splice(2)
this.fileToCopy = this.argument[0]
this.destination = this.argument[1] ? this.argument[1] : ''
this.callAdress = process.cwd()
this.finalAdress = `${this.callAdress}\\` + this.destination
;(async () => {
if (await this.fileExists(this.fileToCopy, this.finalAdress))
console.log('EXISTS')
else console.log('DOESNT EXISTS')
})()
}
async fileExists(file, path) {
try {
let files = await fs.readdir(path)
return files.includes(file)
} catch (e) {
console.log('ERROR', e)
return false
}
}
}
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.
So I'm trying to run a few checks inside a file. Lets say inside checks.js I have
module.exports = async (content) => {
// Check no.1
if (content.id != 'SomeID') return;
// Check no.2
if (content.length > 20) return;
//..etc
}
And in my main file I am requiring this file. I want it to return in the original file depending on the outcome of checks.js So lets say the content id isn't the same as 'SomeID', I want it to return and not to continue the rest of the code in my main file. I did require('filePath')(content) But it doesn't actually return in the main file as it should by instructions in checks.js What am I doing wrong and what should I be doing. Thank you in advance!
checks.js is returning an AsyncFunction, you must await it.
checks.js:
module.exports = async (content) => {
// Check no.1
if (content.id != 'SomeID') return;
// Check no.2
if (content.length > 20) return;
//..etc
return true // maybe your not returning truthy?
}
index.js:
const checks = require('./checks');
(async () => {
console.log('typeof checks()', typeof checks);
console.log('instance of', checks.constructor.name);
//
let content = {
id: 'SomeID'
};
if (await checks(content)) {
console.log('1. passed');
} else {
console.log('1. failed');
}
//
content = {
id: 'WrongID'
};
if (await checks(content)) {
console.log('2. passed');
} else {
console.log('2. failed');
}
})();
Will output when run:
typeof checks() function
instance of AsyncFunction
1. passed
2. failed
See Understanding async/await on NodeJS for more details.
First I have the following code section:
export default class Recipe {
constructor(recID) {
this.RecipeID = recID;
}
async GetRecipe() {
try {
let Result = await Axios(
`https://forkify-api.herokuapp.com/api/get?rId=${this.RecipeID}`
);
this.Tilte = Result.data.recipe.title;
this.Author = Result.data.recipe.publisher;
this.Image = Result.data.recipe.image_url;
this.Url = Result.data.recipe.source_url;
this.Ingredients = Result.data.recipe.ingredients;
this.PublisherUrl = Result.data.recipe.publisher_url;
this.Rank = Result.data.recipe.social_rank;
} catch (error) {
alert(error);
}
}
CalculateTime() {
try {
this.Time = Math.ceil(this.Ingredients.length / 3) * 15; // error is here
} catch (error) {
console.log(this.RecipeID + ": Length Error->"+error);
}
}
}
Then I call the above code in a separate file like:
import Recipe from "./Recipe";
const RecipeController = async () => {
const ID = window.location.hash.replace("#", "");
if (ID) {
AppState.Recipe = new Recipe(ID);
try {
await AppState.Recipe.GetRecipe();
AppState.Recipe.CalculateTime();
console.log(AppState.Recipe);
} catch (error) {
alert(error);
}
}
};
Now as shown in the following image, that I do get the response of the request & promised is resolved plus there are elements in the 'ingredients' array but sometimes I still get the error "cannot read property 'length' of undefined" when I call the 'CalculateTime()' although the array is now defined and sometimes I don't get any error & it works perfectly fine.Why this random behavior? Even the IDs in the JSON response & the error I logged match i.e. 47746.
This is one reason why having too many try/catches can obscure the causes of errors, making debugging difficult. The problem can be reduced to the following:
class Recipe {
constructor(recID) {
this.RecipeID = recID;
}
async GetRecipe() {
let Result = await fetch(
`https://forkify-api.herokuapp.com/api/get?rId=47746`
).then(res => res.json());
console.log(Result); // <----- look at this log
this.Tilte = Result.data.recipe.title;
// on the above line, the error is thrown
// Cannot read property 'recipe' of undefined
}
}
const r = new Recipe();
r.GetRecipe();
See the log: your Result object does not have a .data property, so referencing Result.data.recipe throws an error. Try Result.recipe instead:
class Recipe {
constructor(recID) {
this.RecipeID = recID;
}
async GetRecipe() {
let Result = await fetch(
`https://forkify-api.herokuapp.com/api/get?rId=47746`
).then(res => res.json());
const { recipe } = Result;
this.Tilte = recipe.title;
this.Author = recipe.publisher;
this.Image = recipe.image_url;
this.Url = recipe.source_url;
this.Ingredients = recipe.ingredients;
this.PublisherUrl = recipe.publisher_url;
this.Rank = recipe.social_rank;
}
CalculateTime() {
this.Time = Math.ceil(this.Ingredients.length / 3) * 15; // error is here
console.log('got time', this.Time);
}
}
(async () => {
const r = new Recipe();
await r.GetRecipe();
r.CalculateTime();
})();
Unless you can actually handle an error at a particular point, it's usually good to allow the error to percolate upwards to the caller, so that the caller can see that there was an error, and handle it if it can. Consider changing your original code so that RecipeController (and only RecipeController) can see errors and deal with them - you can remove the try/catches from the Recipe.
Are you sure some of the responses are not missing ingredients? And calculateTime is always called after getRecipe?
I would add a condition or fallback to prevent errors, as in.
this.Time = Math.ceil((this.Ingredients || []).length / 3) * 15;
I would speculate that this "random" behavior can be related to asynchronous code. You need to ensure that the class has Ingredients in place before you calculate. I have a feeling that you should try changing your syntax to a Promise handling using .then() and .catch(), especially since you already use try/catch in your code. This approach will ensure proper resolution of Promise on axios request, and will eliminate "randomness", because you will have a better control over different stages of Promise processing.
let Result = await Axios(
`https://forkify-api.herokuapp.com/api/get?rId=${this.RecipeID}`
)
.then((data) => {
this.Tilte = data.data.recipe.title;
this.Author = data.data.recipe.publisher;
this.Image = data.data.recipe.image_url;
this.Url = data.data.recipe.source_url;
this.Ingredients = data.data.recipe.ingredients;
this.PublisherUrl = data.data.recipe.publisher_url;
this.Rank = data.data.recipe.social_rank;
this.Ingerdients = data.data.recipe.ingredient;
}
.catch((err) => {
console.log(err);
return null;
});
I would like to know if it is somehow possible to check if an asynchronous operation in Javascript is still pending..
Because I am doing a database request on calling a specific URL... While the db call is still in progress, I want to stop any other incoming db-calls (which means, stop any further calls to that URL in case the db-request is still pending).
Is that somehow possible?
Because the database call takes up to minutes, and I don't want to launch another database-call while the first is still in progress.. The problem is, I somehow cannot figure out how to check if the call has started and is still in progress, because the response comes only after the .then() clause when the process has already finished.
this is my db-call function:
const getWriteIndex = async () => {
return Promise.all(someFunction1, someFunction2...).then(...) {
writeMessageObject = checkDocuments(...);
return Promise.resolve(writeMessageObject);
})).catch((err) => {
return Promise.reject(err);
});
}
This is my URL/Route Call function with express:
router.get("/v1/...", someMiddleware(), async function(req,res,next) {
if (read_cached() && initialised_read) {
res.setHeader('Content-Type', 'application/json');
res.json(readmsg_obj);
} else {
try {
//HOW CAN I CHECK HERE IF THE DB-CALL IS ALREADY IN PROGRESS?
readmsg_obj.message = '';
getReadIndex().then((message) => {
initialised_read = true;
readmsg_obj = {...message};
res.setHeader('Content-Type', 'application/json');
res.json(readmsg_obj);
}).catch((reject) => {
logger.error(`/../... : ${reject}`);
initialised_read = false;
res.status(500).send(reject);
});
} catch(err) {
logger.error(`/v1/... : ${err}`);
res.status(500).send(err);
};
}
});
hmm I found a workaround here:
https://ourcodeworld.com/articles/read/317/how-to-check-if-a-javascript-promise-has-been-fulfilled-rejected-or-resolved
so I wrote that function to check for promise stati, but I am still wondering if it's not somehow possible to query for static promise properties to get their actual state ;) (but weirdly, I didn't find any on the web).
const checkPendingRequest= (promise) => {
if (promise.isResolved) return promise;
// Set initial state
var isPending = true;
var isRejected = false;
var isFulfilled = false;
// Observe the promise, saving the fulfillment in a closure scope.
var result = promise.then(
function(v) {
isFulfilled = true;
isPending = false;
return v;
},
function(e) {
isRejected = true;
isPending = false;
throw e;
}
);
result.isFulfilled = function() { return isFulfilled; };
result.isPending = function() { return isPending; };
result.isRejected = function() { return isRejected; };
return result;
}
So I fixed my function for the request:
router.get("/v1/...", someMiddleware(), async function(req,res,next) {
if (read_cached() && initialised_read) {
res.setHeader('Content-Type', 'application/json');
res.json(readmsg_obj);
} else {
try {
readmsg_obj.message = '';
if ((dbQueryPromiseRead != null) && dbQueryPromiseRead.isPending()) {
logger.info(`Database request for Index-read is still pending!`);
return;
}
dbQueryPromiseRead = checkPendingRequest(getReadIndex());
dbQueryPromiseRead.then((message) => {
initialised_read = true;
readmsg_obj = {...message};
res.setHeader('Content-Type', 'application/json');
res.json(readmsg_obj);
}).catch((reject) => {
logger.error(`/../... : ${reject}`);
initialised_read = false;
res.status(500).send(reject);
});
} catch(err) {
logger.error(`/v1/... : ${err}`);
res.status(500).send(err);
};
}
});
You need to try add in node.js like global.dbCallState flag if operation is still running.
This global var one for all modules.
Do not change this object like global = new Object();, but you can use child field's.
https://nodejs.org/api/globals.html
You can change it in another module like global.dbCallState = false.
It not best solution, but it can help.
But i don't know, why you want only one connection. Its not good solution to block I/O in node.js
So I am using Vue.js, which is not the problem I know, it is just something I'm doing wrong, and there is a reason I'm doing it this way, but I keep getting an error like its not an array.
Code:
methods: {
async register() {
this.errors = '';
this.success = '';
await RegisterService.insertUser(this.email, this.username, this.password, this.passwordTwo)
.then(data => {
if (data.data) {
let v = Object.values(data.data);
console.log(v);
v = v.replace(/["[]]/g, '');
this.errors = v;
} else {
this.success = `Registration Successful!`;
}
});
}
}
So what I am getting is v.replace is not a function, I'm sure there is a simple reason for this and I am just whiffing at figuring it out.