Return upon another file check - javascript

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.

Related

Get and check a value from JSON read in NodeJS

I'm trying to check if a user exists (registered on a json file).
Unfortunately I don't find a valid solution in all Stack Overflow that gives me a simple "true" in a callback.
The version closest to a solution
Experiment V1 :
let userExist;
function check(){
console.log("CHECK!");
return userExist = true;
}
// check(); if this, return true... obvious.
//// check if user exist
server.readFileSync(filepath, 'utf8', (err, data) =>
{
let json = JSON.parse(data),
userlist = json.allusers;
for (let key in userlist)
{
if ( userlist[key].email == req.body.user_email )
{
console.log("FINDED EQUAL");
check(); // return undefined ???
}
}
});
console.log("userExist value : "+userExist);
differently formulated the debugs also appear, but "true" never returns.
note: yes, JSON is read correctly. If everything works inside the readfile, you immediately notice the same emails.
output: "undefined"
Log: total bypassed
Experiment V2 :
In this case (with asynchronous reading) it returns all the debugging (but the "true" remains undefined)
The problem with the asynchronous is that I have to wait for it to check to continue with the other functions.
//// check if user exist
server.readFile(filepath, 'utf8', (err, data) =>
{
let json = JSON.parse(data),
userlist = json.allusers;
for (let key in userlist)
{
if (/* json.allusers.hasOwnProperty(key) &&*/ userlist[key].email == req.body.user_email )
{
console.log("FINDED EQUAL");
check();
}
}
});
var userExist;
function check(userExist){
console.log("CHECK!");
return userExist=true;
}
console.log("userExist value : "+userExist+"");
server listening on: 8080
userExist value : undefined
CHECK!
FINDED EQUAL
Experiment V3 :
after the various suggestions I come to a compromise by using the syntax for the async functions.
This allowed to reach an ordered code, but despite this it is not possible to wait for the results and export them out of the same function (this is because node itself is asynchronous! Therefore it has already gone on!)
using a "message" variable to check if it could return an object I did so:
//simple output tester
var message;
// create a promise
let loopusers = new Promise( (resolve)=>{
server.readFile( filepath, 'utf8',
(err, data) => {
let json = JSON.parse(data),
userlist = json.allusers,
findedequal;
console.log("CHECK USERS IN DB...for "+userlist.length+" elements");
// loop all items
for (let key in userlist)
{
console.log("Analyzed key ::: "+key);
if ( userlist[key].email == req.body.user_email )
{
console.log("CHECK : user isn't free");
findedequal=true;
resolve(true); // return the result of promise
}
else if(key >= userlist.length-1 && !findedequal )
{
console.log("CHECK : User is free ;)");
resolve(false); // return the result of promise
}
}
// call the action
createuser();
});
});
// when promise finished --> start action
async function createuser(message)
{
let userExist = await loopusers;
console.log("userExist: "+userExist);
if(userExist)
{
message = { Server: "This user already exists, Try new e-mail..."};
}
else
{
message = { Server: "Registration user -> completed..."};
}
// return values
return message;
};
It is also possible to use the classic syntax via "then". For exemple:
//simple output tester
var message;
// create a promise
let loopusers = new Promise( (resolve)=>{
...
});
loopusers.then( (response)=>{
...
})
Then I realized that it was easy to simplify even more by calling the functions directly from the initial one:
var message;
// create a promise --> check json items
server.readFile( filepath, 'utf8',
(err, data) => {
let json = JSON.parse(data),
userlist = json.allusers,
findedequal;
console.log("CHECK USERS IN DB...for "+userlist.length+" elements");
for (let key in userlist)
{
console.log("Analyzed key ::: "+key);
if ( userlist[key].email == req.body.user_email )
{
console.log("CHECK : user isn't free");
findedequal=true;
createuser(true); // call direct function whit params true
}
else if(key >= userlist.length-1 && !findedequal )
{
console.log("CHECK : User is free ;)");
createuser(false); // call direct function whit params false
}
}
});
// start action
function createuser(userExist)
{
if(userExist)
{
message = { Server: "This user already exists, Try new e-mail..."};
}
else
{
message = { Server: "Registration user -> completed!"};
}
// return values
return message;
};
debugging is taken and written
the message is lost outside the aSync function
Experiment V4 Final! :
Finally, after many attempts the solution! (Yes... But know it's not Async)
If we allocate in a variable the reading becomes synchronous the whole model and we return to the simple one
let message,
file = server.readFileSync(filepath, 'utf8'), // read sync
json = JSON.parse(file), // now parse file
userlist = json.allusers, // get your target container object
userExist,
findedequal;
console.log("CHECK USERS IN DB...for "+userlist.length+" elements");
for (let key in userlist)
{
console.log("Analyzed key ::: "+key);
if ( userlist[key].email == req.body.user_email )
{
console.log("CHECK : finded equal value on key ["+key+"] - user isn't free");
findedequal=true;
userExist = true;
}
else if(key >= userlist.length-1 && !findedequal )
{
console.log("CHECK : User is free ;)");
userExist = false;
}
}
if(userExist)
{
console.log("└ EXIT TO CHECK --> Can't create user, function stop.");
message = { Server: "This user already exists, Try new e-mail..."};
}
else
{
console.log("└ Exit to check --> New user registration ...");
message = { Server: "Registration user -> completed!"};
}
}
return message;
Now:
It's all sync and all log is perfect
all var is checked
all return... return
** Final conclusions: **
Is it possible to retrieve an ASync variable in node?
As far as I understand so far ... no.
Node is async by its nature, therefore recovering information that is not saved and then recovered from a DB is left behind among the things to do, becoming unrecoverable if you use it as in this post.
However ... if the purpose is to make reading a file synchronous, the answer was simpler than expected.
A special thanks to: Barmar; Austin Leehealey; C.Gochev;
The problem is that you are calling console.log("userExist value : "+userExist+"");
too early. At the moment that you call that line, userExist is not defined yet. This is because the server.readFile() function requires a callback and that callback function is executed once it has read the file. However, reading files often take time and so the program keeps going. It executes console.log("userExist value : "+userExist+""); and then goes back to the callback function and defines userExist as true.
If you want more information on what callbacks are look at the link below. Callbacks are a defining feature of Nodejs and understanding them is essential to any Node website.
https://medium.com/better-programming/callbacks-in-node-js-how-why-when-ac293f0403ca
Try something like this.
let userExist;
function check(){
console.log("CHECK!");
return userExist = true;
}
// check(); if this, return true... obvious.
//// check if user exist
server.readFileSync(filepath, 'utf8', (err, data) =>
{
let json = JSON.parse(data),
userlist = json.allusers;
for (let key in userlist)
{
if ( userlist[key].email == req.body.user_email )
{
console.log("FINDED EQUAL");
check(); // return undefined ???
console.log("userExist value : "+userExist);
}
}
});

looping the callback function in node js

This is a piece of code which writes data to a ble device and reads data from it. data is written to the device in the form of a buffer. the value in 'mydata' (AAAD0000) is the command to be written in order to read the data.
function named chara3() consists of write and read function which is a callback function in which the command is passed read back.
My requirement is the 'mydata' value which i said earlier, the last two zeros is the memory address. i need to read the data in different memory addresses starting from zero to 59. That is AAAD0000 to AAAD0059. so of course i need to run a loop. If I'm reading the zeroth location, the code is quite fine and i got the output as well but when i tried to make it inside a loop, the code is all a mess. the read part is not executing.
can any one suggest a better way to read data from zeroth memory location to 59th memory location (AAAD0000 to AAAD0059)???
first command writes to it
then reads data
memory location incremented by 1
this should repeat up to 59
var mydata = 'AAAD0000';
function chara3() {
var buff2 = new Buffer(mydata, 'hex');
SensorCharacteristic.write(buff2, false, function(error) { //[0x002d]
console.log('Writing command SUCCESSFUL',mydata);
if (!error) {
SensorCharacteristic.read((error, data) => {
console.log("i just entered");
if (data.toString('hex') != '0000') {
console.log('Temperature History: ', data.toString('hex'));
enter();
}
else {
console.log('contains null value');
} //else
});
}
function enter()
{
mydata = (parseInt(mydata, 16) + 00000001).toString(16);
}
}); //.write
} //chara3
there's no error. But some part of the code is not executing.
You can use the recursion by wrapping your methods into a promise
async function chara3(mydata = 'AAAD0000') {
if (mydata === 'AAAD0059') {
return;
}
var buff2 = new Buffer(mydata, 'hex');
return new Promise((resolve) => {
SensorCharacteristic.write(buff2, false, function (error) { //[0x002d]
console.log('Writing command SUCCESSFUL', mydata);
if (!error) {
SensorCharacteristic.read(async (error, data) => {
console.log("i just entered");
if (data.toString('hex') != '0000') {
console.log('Temperature History: ', data.toString('hex'));
let next = await chara3(enter())
return resolve(next);
}
else {
console.log('contains null value');
return resolve();
} //else
});
}
}); //.write
});
} //chara3
function enter() {
return (parseInt(mydata, 16) + 00000001).toString(16);
}
Also if you can convert your methods SensorCharacteristic.write and SensorCharacteristic.read into promises you can simply map
function chara3(mydata) {
var buff2 = new Buffer(mydata, 'hex');
await SensorCharacteristic.write(buff2, false);
console.log('Writing command SUCCESSFUL', mydata);
let data = await SensorCharacteristic.read();
if (data.toString('hex') != '0000') {
console.log('Temperature History: ', data.toString('hex'));
enter();
} else {
console.log('contains null value');
}
};
let promiseArray = Array(60).fill().map((_, i) => (parseInt('AAAD0000', 16) + i).toString(16)).map(chara3);
Promise.all(promiseArray).then(() => console.log('done'));

Conditional async callbacks

I'm writing an Electron program which takes a CSV file as input, and does file operations depending on the CSV content and file existence (it's to manage MAME arcade roms).
In order to have a progress bar on the UI side, I have switched the code from fully synchronous (because it was much easier) to asynchronous.
I just cannot find out how to reliably display a message to the user when all the lines in the CSV file are processed, and all the zip files are copied or removed.
Here is a (simplified) sample method:
fs.readFile(file, { 'encoding': 'utf8' }, (err, fileContents) => {
let fileCsv = csvparse(fileContents);
let lines = fileCsv.length;
fileCsv.forEach((line) => {
lines--;
let zip = line.name + '.zip';
let sourceRom = path.join(romset, zip);
let destRom = path.join(selection, zip);
this.emit('progress.add', fileCsv.length, fileCsv.length - lines, zip);
if (fs.existsSync(sourceRom) && !fs.existsSync(destRom)) {
fs.copy(sourceRom, destRom, (err) => {
let sourceChd = path.join(romset, game);
if (fs.existsSync(sourceChd)) {
fs.copy(sourceChd, path.join(selection, game), (err) => {
if (lines <= 0) { callback(); } // chd is copied
});
} else {
if (lines <= 0) { callback(); } // no chd, rom is copied
}
});
} else {
if (lines <= 0) { callback(); } // no source found or already exists
}
});
});
The problem is that the CSV file is processed really fast, but the file are not copied as fast. So it decrements the lines counter to 0, then after each file copy, it finds that it's zero and triggers the callback.
How do I reliably trigger the callback at the end of all these nested callbacks and conditions?
Thanks
I tried to change the code without massively overwriting your style - assuming there is a reason to avoid things like bluebird, async/await & native Promises, and the async lib.
You need to decrement lines after a line is processed. I pulled the processing logic out into a function to make this clearer:
function processLine({
sourceRom, destRom, romset, game, callback
}) {
if (fs.existsSync(sourceRom) && !fs.existsSync(destRom)) {
fs.copy(sourceRom, destRom, (err) => {
// *really* should handle this error
let sourceChd = path.join(romset, game);
if (fs.existsSync(sourceChd)) {
fs.copy(sourceChd, path.join(selection, game), (err) => {
// *really* should handle this error
callback();
});
} else {
callback();
}
});
} else {
callback() // no source found or already exists
}
}
fs.readFile(file, { 'encoding': 'utf8' }, (err, fileContents) => {
let fileCsv = csvparse(fileContents);
let lines = fileCsv.length;
fileCsv.forEach((line) => {
let zip = line.name + '.zip';
let sourceRom = path.join(romset, zip);
let destRom = path.join(selection, zip);
this.emit('progress.add', fileCsv.length, fileCsv.length - lines, zip);
processLine({ sourceRom, destRom, game, romset, callback: () => {
lines--;
if (lines <= 0) {
callback();
}
}})
});
});

Why is the function running before AsyncStorage is finished

im here with an issue regarding react native, i started a project about 2 weeks ago and its the first time im trying this framework and never worked with javascript ever so its being hard...
What i would like to know is why my function called 'check_Authentication' wich just checks if the variables of a .js file called 'Globals" that have the default values presetted runs before i can finish my AsyncStorage tasks to asign it new ones
Here is my code
this two function as you can see are AsyncStorage and after i either get an item or set one...i call a funtion called 'Update_Globals' that is in another .js file and update my global variables from my other .js file called 'Globals' so that i can use them later on.
async function set_Async(field, value){
try {
await AsyncStorage.setItem(field, value);
await update_Globals(field,value);
} catch (error) {
throw new Error('something wrong with setting async storage');
}
}
async function get_Async(field){
try {
const value = await AsyncStorage.getItem(field);
await update_Globals(field,value);
} catch (error) {
throw new Error('something wrong with getting async storage');
}
}
Here is the .js file with the function to update my global variables mentioned above
import globals from './globals.js';
export function update_Globals(field,value){
alert("Updating field: " + field + " with value: " + value);
switch(field) {
case globals.is_logged_in_name:
globals.is_logged_in_value = value;
break;
case globals.account_status_name:
globals.account_status_value = value;
break;
case globals.account_role_name:
globals.account_role_value = value;
break;
case globals.account_user_name:
globals.account_user_value = value;
break;
case globals.account_api_token_name:
globals.account_api_token_value = value;
break;
case globals.account_profile_status_name:
globals.account_profile_status_value = value;
break;
default:
alert("No variable found")
}
}
and here is the .js file with the variables
module.exports = {
is_logged_in_name: 'is_logged_in',
is_logged_in_value: 'false',
account_status_name: 'account_status',
account_status_value: '0',
account_role_name: 'account_role',
account_role_value: '0',
account_user_name: 'account_user',
account_user_value: '0',
account_api_token_name: 'account_api_token',
account_api_token_value: '0',
account_profile_status_name: 'account_profile_status',
account_profile_status_value: 'empty',
testing_name: "name",
testing_value: "Chrystello",
};
and this function is where it all goes together
async function do_Login(){
return fetch(url, {
method: method,
headers: headers,
body: JSON.stringify({
email: email,
password: password,
firebase_token: firebase_token,
})
})
.then(function(responseData) {
if(responseData.ok){
return responseData.json();
}
throw new Error('Network response was not ok.');
})
.then(function(responseData) {
const response = responseData["response"];
const response_array = response[0];
set_Async(globals.account_user_name,
replace_Quote_Marks(JSON.stringify(response_array["user_id"]))).done();
set_Async(globals.account_status_name,
replace_Quote_Marks(JSON.stringify(response_array["status_id"]))).done();
set_Async(globals.account_profile_status_name,
replace_Quote_Marks(JSON.stringify(responseData["status"]))).done();
set_Async(globals.account_role_name,
replace_Quote_Marks(JSON.stringify(response_array["role_id"]))).done();
set_Async(globals.account_api_token_name,
replace_Quote_Marks(JSON.stringify(response_array["api_token"]))).done();
})
.then(function () {
try{
check_Authentication()
}catch(error){
throw new Error("couln't run function");
}
})
.catch(function(error) {
console.error(error);
});
}
in here you can see me calling the set_Async() function where i send the name and value i want to store and after it is suposed to update my .js file with the new values and after the 5 are done i then procede to checking each value to then decide wether the user can or can't log in but it always return the default number the first time i click the button, the second time works because he has the new values so i can only asume that the function check_Authenticantion is running before the AsyncStorages
the function check_aunthentication is this one
function check_Authentication() {
Alert.alert("I Got user " + globals.account_user_value)
if(globals.account_user_value != "0"){
const account_status = check_Account_Status(globals.account_status_value)
return_value = JSON.stringify(account_status["return_value"])
if(return_value == "true"){
screen = JSON.stringify(account_status["screen"]);
if(screen == "ForcePassword"){
return true;
}
const account_profile = check_Account_Profile(globals.account_profile_status_value)
return_value = JSON.stringify(account_profile["return_value"])
if(return_value == "true"){
screen = JSON.stringify(account_profile["screen"])
const account_role = check_Account_Role(globals.account_role_value)
return_value = JSON.stringify(account_role["return_value"])
if(return_value == "true"){
screen = JSON.stringify(account_role["screen"]) + screen
screen = replace_Quote_Marks(screen)
return true;
}else{
message = JSON.stringify(account_profile["message"])
Alert.alert(message)
return false;
}
}else{
message = JSON.stringify(account_profile["message"])
Alert.alert(message)
return false;
}
}else{
message = JSON.stringify(account_status["message"])
Alert.alert(message)
return false;
}
}else{
Alert.alert("No User Found")
return false;
}
}
and this is how i run the main function to trigger all the events
<TouchableHighlight
style = {styles.submit_button}
onPress={() => {
do_Login().done()
}
}>
<Text style = {styles.submit_text}>Login</Text>
</TouchableHighlight>
i have found a work arround, might not be the best option but id did the trick..
Removing the await from the AsyncStorage functions somehow made the check_Authentication wait for AsyncStorage to finish setting the values
thanks #SLaks for your time

What's the best(right) way to write a polling method (with Typescript & AngularJS)?

I am trying to write a polling method that polls a server periodically to check whether a zip file has already been created or not.
What I want to accomplish are the following:
Calls(ajax) an API that creates a zip file on server
Calls(ajax) another API that checks if the zip file has already been created (polling method)
Some subsequent process
Here is my code snippet ↓
var success: boolean = false;
//1. requests a server to create a zip file
this.apiRequest.downloadRequest(params,ApiUrl.URL_FOR_DOWNLOAD_REQUEST)
.then((resObj) => {
var apiRes: IDownloadService = resObj.data;
if (apiRes.status[0].statusCode == "000") {
success = true;
} else {
//Error
}
}).then(() => {
if (success) {
//2. polls the server to check if the zip file is ready
<- Polling method↓ ->
this.polling(params).then((zipUrl) => {
console.log(zipUrl); //always logs zipUrl
//some subsequent process...
});
}
});
Could anyone give some examples of polling method that would work in this case?
Added:
private polling(params: any): ng.IPromise<any> {
var poller = () => this.apiRequest.polling(params, ApiUrl.URL_FOR_POLLING);
var continuation = () => poller().then((resObj) => {
var apiRes: IDownloadService = resObj.data;
if (apiRes.zipFilePath == "") {
return this.$timeout(continuation, 1000);
} else {
return apiRes.zipFilePath;
}
})
var result: ng.IPromise<any> = continuation();
return result;
}
Basically abstract the methods out as shown below:
let poll = () => this.apiRequest.downloadRequest(params,ApiUrl.URL_FOR_DOWNLOAD_REQUEST)
let continuation = () => poll().then((/*something*/)=> {
/*if still bad*/ return continuation();
/*else */ return good;
})
continuation().then((/*definitely good*/));
Update
As requested in the comment below:
return this.$timeout(continuation, 1000);
This is needed to get angular to kick off a digest cycle.

Categories