Firebase - remote config on web sometimes gets values and sometimes not - javascript

I'm new to programming in Javascript (I haven't even been programming for a month, but I have experience in other non-asynchronous languages).
I'm having trouble connecting the Firebase config to my website, sometimes it shows values, other times it doesn't.
if (app_data) {
console.log("Step 0");
remoteConfig = getRemoteConfig(app_data);
remoteConfig.settings.minimumFetchIntervalMillis = 10000;
} else {
console.log("No se ha podido conectar a la base de datos.");
}
if (fetchAndActivate(remoteConfig)) {
console.log("Paso por 2");
obj_config = getAll(remoteConfig);
console.log("Paso por 3");
Object.entries(obj_config).forEach((x) => {
const [key, entry] = x;
if (key === "contract_address") {
contract_token = entry["_value"];
console.log("Key Address: ", entry["_value"]);
}
console.log("Key: ", key);
console.log("Source: ", entry.getSource());
console.log("Value: ", JSON.stringify(entry["_value"]));
});
}
If someone could help me, I would be very grateful.
Greetings

fetchAndActivate is async, so it won't have finished fetching yet:
instead of
if (fetchAndActivate(remoteConfig)) {
//code
}
try
fetchAndActivate(remoteConfig).then(() => {
// code
});

If you are using Javascript, you could try to use await in your code because the fetching step is asynchronous.
Something like
const rcResult = await asyncFetchFromRC()

Related

JS - How to retrieve variable after IndexedDB transaction.oncomplete() executes?

My problem is simple, but incredibly frustrating as I'm now on my second week of trying to figure this out and on the verge of giving up. I would like to retrieve my 'notesObject' variable outside my getAllNotes() function when after the transaction.oncomplete() listener executes.
(function() {
// check for IndexedDB support
if (!window.indexedDB) {
console.log(`Your browser doesn't support IndexedDB`);
return;
}
// open the CRM database with the version 1
let request = indexedDB.open('Notes', 1);
// create the Contacts object store and indexes
request.onupgradeneeded = (event) => {
let db = event.target.result;
// create the Notes object store ('table')
let store = db.createObjectStore('Notes', {
autoIncrement: true
});
// create an index on the sections property.
let index = store.createIndex('Sections', 'sections', {
unique: true
});
}
function insertData() {
let myDB = indexedDB.open('Notes');
myDB.onsuccess = (event) => {
// myDB.transaction('Notes', 'readwrite')
event.target.result.transaction('Notes', 'readwrite')
.objectStore('Notes')
.put({
sections: "New Note",
pages: "New page",
lastSelectedPage: ""
});
console.log("insert successful");
}
myDB.onerror = (event) => {
console.log('Error in NotesDB - insertData(): ' + event.target.errorCode);
}
myDB.oncomplete = (event) => {
myDB.close();
console.log('closed');
}
}
insertData()
function getAllNotes() {
let myDB = indexedDB.open('Notes');
let notesObject = [];
myDB.onsuccess = (event) => {
let dbObjectStore = event.target.result
.transaction("Notes", "readwrite").objectStore("Notes");
dbObjectStore.openCursor().onsuccess = (e) => {
let cursor = e.target.result;
if (cursor) {
let primaryKey = cursor.key;
let section = cursor.value.sections;
notesObject.push({
primaryKey,
section
})
cursor.continue();
}
}
dbObjectStore.transaction.onerror = (event) => {
console.log('Error in NotesDB - getAllData() tranaction: ' + event.target.errorCode);
}
dbObjectStore.transaction.oncomplete = (event) => {
return notesObject;
console.log(notesObject)
}
}
}
let notes = getAllNotes()
console.log("Getting Notes sucessful: " + notes)
})()
I've tried setting global variables, but nothing seems to work. I am a complete noob and honestly, I'm completely lost on how to retrieve the notesObject variable outside my getAllNotes() function. The results I get are 'undefined'. Any help would be greatly appreciated.
This is effectively a duplicate of Indexeddb: return value after openrequest.onsuccess
The operations getAllNotes() kicks off are asynchronous (they will run in the background and take time to complete), whereas your final console.log() call is run synchronously, immediately after getAllNotes(). The operations haven't completed at the time that is run, so there's nothing to log.
If you search SO for "indexeddb asynchronous" you'll find plenty of questions and answers about this topic.

fs.writeFile does not respect the order of execution of functions (it always executes last)

I started tinkering with JavaScript (Node) recently, and I'm having a problem with a function that performs file writing. This function is always executed last, regardless of the calling order, and I can't fix it, could someone help me? (For example, in the code below, the categorySumPrice() function should run after the createAndWriteFixedJsonFile() function, but it runs before)
This is the program:
// ********************* CLASSES ****************
class Produto {
constructor(id, name, quantity, price, category) {
this.id = id
this.name = name
this.quantity = quantity
this.price = price
this.category = category
}
}
// ********************* Procedural *************
// ------ Global variables
// vector of objects produto
var produtos = []
// file name
const fileName = "broken-database.json"
//fixed file name
const fixedFileName = "./arquivo.json"
// file open require
const fs = require("fs")
//Read and Writing modes, like C
/*
r - Open file for reading
r+ - Open file for reading and writing
rs - Open file for reading synchronous mode
rs+ - Open file for reading and writing, synchronous mode
w - Open file for writing synchronous mode (if not exists file, created that)
wx - Open file for writing (if not exists file, dont created that)
w+ - Open file for writing and reading (if not exists file, created that)
wx+ - Open file for writing and reading (if not exists file, dont created that)
*/
// Fix JSON Part
// open broken database
var jsonFileName = openFile(fileName)
//read json file, fix, if necessary, and create objects produto
readFile(jsonFileName)
//save new JSON file fixed
createAndWriteFixedJsonFile(fixedFileName)
//sum price functions
categorySumPrice()
// ********************* FUNÇÕES *************
// Open File
function openFile(_file_name) {
try {
console.log('********************************')
console.log('* Arquivo aberto com sucesso *')
console.log('********************************')
return fs.readFileSync(_file_name, 'utf-8')
} catch (err) {
console.error(err)
}
}
// Fix JSON File and create objects produto
function readFile(_json_File) {
// Create produtos objects
try {
console.log('********************************')
console.log('* Os dados serão corrigidos, *')
console.log('* se necessário. *')
console.log('********************************')
const data = JSON.parse(_json_File)
for (var i in data) {
produtos[i] = new Produto(parseInt(data[i].id), fixString(data[i].name),
fixQuantity(data[i].quantity), fixPrice(data[i].price), data[i].category)
}
console.log('********************************')
console.log('* Dados obtidos com sucesso *')
console.log('********************************')
}
catch (err) {
console.log(`Erro: ${err}`)
}
}
// create and write fixed Json file
function createAndWriteFixedJsonFile(_fixedFileName) {
try {
fs.writeFile(_fixedFileName, JSON.stringify(produtos, null, 2), err => {
if (err) {
console.log(err)
}
else {
console.log('********************************')
console.log('* Arquivo criado com sucesso *')
console.log('********************************')
}
})
} catch (err) {
console.error(err)
}
}
function fixQuantity(quantityToFix) {
let quantity
if (isNaN(quantityToFix)) {
quantity = 0
}
else {
quantity = parseFloat(quantityToFix)
}
return quantity
}
function fixPrice(priceToFix) {
return parseFloat(priceToFix)
}
// Fix string function
function fixString(stringToFix) {
// Quatro tipos de erros conhecidos:
/*
"a" por "æ",
"c" por "¢",
"o" por "ø",
"b" por "ß".
*/
// o /g significará que todos os valores correspondentes serão substituídos.
// por padrão, replace substitui somente a primeira ocorrência
stringToFix = stringToFix.replace(new RegExp(/æ/g), "a");
stringToFix = stringToFix.replace(new RegExp(/¢/g), "c");
stringToFix = stringToFix.replace(new RegExp(/ø/g), "o");
stringToFix = stringToFix.replace(new RegExp(/ß/g), "b");
return stringToFix
}
function categorySumPrice() {
let estoquePorCategoria = []
let indice
let countCategories = 0
for (var i in produtos) {
if (i === 0) {
estoquePorCategoria[countCategories] = { categoria: produtos[i].category, valor: (produtos[i].quantity * produtos[i].price) }
countCategories++
}
else {
indice = estoquePorCategoria.indexOf(estoquePorCategoria.filter(function (obj) {
return obj.categoria == produtos[i].category;
})[0]);
if (indice != -1) {
estoquePorCategoria[indice].valor += (produtos[i].quantity * produtos[i].price)
}
else {
estoquePorCategoria[countCategories] = { categoria: produtos[i].category, valor: (produtos[i].quantity * produtos[i].price) }
countCategories++
}
}
}
console.log(estoquePorCategoria)
}
writeFile is an asynchronous function, which means that it will execute in parallel to other things. So:
You call writeFile then it starts writing.
The rest of your code continues executing while it's writing.
The writeFile finishes writing.
In order to have it execute synchronously with your other code you need to use writeFileSync.
You should use writeFile when the rest of your code isn't dependent on that file and writeFileSync if it is.
You can use fs.writeFileSync, this will run according to your work flow.
Learn more about it here - https://www.geeksforgeeks.org/node-js-fs-writefilesync-method/
fs.writeFile() is executed asynchronously meaning that categorySumPrice() comes ahead of createAndWriteFixedJsonFile() because it takes time to save the file.
To avoid this you need to call categorySumPrice() from the callback function in fs.writeFile():
// create and write fixed Json file
function createAndWriteFixedJsonFile(_fixedFileName) {
try {
fs.writeFile(_fixedFileName, JSON.stringify(produtos, null, 2), err => {
if (err) {
console.log(err)
}
else {
console.log('********************************')
console.log('* Arquivo criado com sucesso *')
console.log('********************************')
//And now is the time for executing the following:
categorySumPrice();
}
})
} catch (err) {
console.error(err)
}
}

Not finding an easy solution to unban command for Discord Bot

I have been trying to get the unban command to work for the past 2 days, but I haven't found an easy solution for it, I keep getting errors like ".find()" isn't a function, or can't define "id". And I just don't get what I need to do. PS.: I am a noobie when it comes to code.
It's also worth mentioning that I have gone through many variations of this code and I have ended at this, probably previous iterations of the code were closer to the actual solution.
const Discord = require('discord.js');
const client = new Discord.Client();
const prefix = "+";
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on('message', msg => {
const { content } = msg;
if (!content.startsWith(prefix)) return;
const args = content.slice(prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
switch(command) {
case "ping" : {
let latency = Date.now() - msg.createdTimestamp;
let latencyOfAPI = Math.round(client.ws.ping);
msg.reply("This is the latency between the message and the response: " + latency + "." + "\nThis is the API latency: " + latencyOfAPI + ".");
break;
}
case "pong" : {
msg.reply("ping");
break
}
case "ban" : {
const user = msg.mentions.members.first();
if (user) {
msg.guild.members.ban(user);
msg.reply("The user " + user + " has been banned.")
} else {
return msg.reply("There is no one to ban.").catch(console.error);
}
break
}
case "unban" : {
const user = client.users.cache.find(user => user.username == "").id;
let banList = msg.guild.fetchBans();
if(banList = 0) {
return msg.reply("This user isn't in the community, or he is not banned.");
} else {
banList.find(user)
msg.guild.members.unban(user);
msg.reply("User " + user + " has been unbanned.")
}
break
}
}
});
client.login('.....');
Try this:
case "unban" : {
const user = client.users.fetch(args[1]).catch((err) => console.log(err));
user.then((u) => {
if (!args[1]) {
return msg.reply("Enter ID to unban")
} else {
if (u) {
msg.guild.members.unban(u).then(() => {
msg.reply("The user " + u.username + " has been unbanned.")
}).catch((err) => console.log(err))
} else {
return msg.reply("Cannot Find User")
}
}
})
break
Usage: [prefix]unban [ID] e.g [prefix]unban 3426743678738 (type in text channel)
Tip #1: Try to use .then() & .catch() on function which return a promise. You can use .then() to confirm that you've successfully unbanned a user and .catch() to see why there was a issue with unbanning a user.
Tip #2: Make an if statement which checks if the user running this command has the right permissions before trying the code i.e BAN_MEMBERS & ADMINISTRATOR
Also Note: .fetchBans() returns a collection and Promise

Callback and/or Promises javascript

It's been 2 days since I'm trying to understand my error. So far what I've learnt is that i will never be able to bypass "undefined" returned value because i cannot understand callback or promises... I rode all the poste , did some easy exemple , but I 'm not undertanding how to make it happen on my code ...
function realloot(data){
return data;
console.log(`${data}`);
}
function lootbox_openning(callback, user, type, nombre){
let sqlQueryopenbox = `SELECT item_qty FROM users_items WHERE discord_id = '${user}' AND item_id = ${type};`
let token_won=0;
let real_token_won=0;
let common_pp_looted = 0;
let rare_pp_looted = 0;
let epic_pp_looted = 0;
db.query(sqlQueryopenbox, (err, rows) => {
let user_box_real_qty = rows[0].item_qty;
let sql;
if (err) {
real_token_won="sql error";
throw err;
}
if (nombre > user_box_real_qty){real_token_won="error number";}
else {
//function open
if (type==1) {
for (var i = 0; i <= nombre; i++){
token_won=little_box_open();
real_token_won=real_token_won+token_won;
}
var myreturn = callback(real_token_won);
console.log(`${myreturn}`);
return myreturn;
}
if (type==2) {}
if (type==3) {}
}
});
}
//this is a bot discord so huge on.message here...
case "open":
if (!args[1]) return message.channel.send('please give value box | bigbox');
if (args[1] ==='box' ){
if (!args[2]) {message.channel.send ("Specify number please");}
if (args[2]) {
var number = parseInt(args[2]);
if (Number.isInteger(number)){
message.channel.send ("You re openning "+args[2]+" boxes");
**var token_won = lootbox_openning(realloot, message.author.id, 1, args[2]);** //PROBLEM IS HERE
if (token_won==="error number"){message.channel.send ("Vous n'avez pas assez de box !");}
else {message.channel.send ("you won : "+token_won+" tokens !");}
}
else message.channel.send ("Give a valid number");
}
}
Please be gentle, I already hit my head so hard on others posts but it seems like I need more explanations...
async logic is a common place for newcommers to get tripped up on. But, it basically boils down to doing this:
Example of a synchronous code:
(this is assuming that db.query() was written as a sync function, which its not)
function doQuery(id) {
let res = db.query(`SELECT * FROM table WHERE id=${id}`)
return res
}
Example of asynchronous code (which using db.query() as an async function)
function doQuery(id, callback) {
db.query(`SELECT * FROM table WHERE id=${id}`, function(res) {
callback(res)
})
}
The main difference here is that instead of doing return res you have to do callback(res). This will always be the case when working with async code.
And its important to note that once you're in the async world, you can never go back to a sync world. i.e. This is impossible:
// some sync logic
let resultOfAsyncOperation = someAsyncFunction()
// some sync logic
Once you're dealing with callbacks, you have to use callbacks everywhere. This is because the user of an async function has to itself be async. The only exception is if you don't care about what's getting returned or when, you just want it to go off and do some task.
So, this is how these principles applies to your specific chunk of code. This snippet of code is exactly the issue I was describing - you're trying to use an async function inside of sync logic.
var number = parseInt(args[2]);
if (Number.isInteger(number)) {
message.channel.send("You re openning " + args[2] + " boxes"); **
var token_won = lootbox_openning(realloot, message.author.id, 1, args[2]); ** //PROBLEM IS HERE
if (token_won === "error number") {
message.channel.send("Vous n'avez pas assez de box !");
} else {
message.channel.send("you won : " + token_won + " tokens !");
}
} else message.channel.send("Give a valid number");
You'll have to convert this chunk of code to also be async, like this:
message.channel.send("You re openning " + args[2] + " boxes");
function callback(token_won) {
realloot(token_won)
if (token_won === "error number") {
message.channel.send("Vous n'avez pas assez de box !");
} else {
message.channel.send("you won : " + token_won + " tokens !");
}
}
lootbox_openning(callback, message.author.id, 1, args[2]);
(it's possible I didn't fully understand how you intended your original code to work, so take this example with a grain of salt. It shows the principle, but you'll have to tweak it to work for your needs)

sheet js xlsx writeFile callback

I am trying to write multiple csv files from a set of data that I have loaded using the sheet js library. My first attempt was like:
for (let i = 0; i < dataSetDivided.length; i++) {
let exportSet = dataSetDivided[i]
console.log(exportSet)
let ws = XLSX.utils.json_to_sheet(exportSet, {header: finalHeaders})
let wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
let todayDate = this.returnFormattedDate()
let originalFileName = this.state.fileName
let exportFileName = 'import_' + originalFileName + '_' + todayDate + '(part_' + (i + 1) + ').csv'
XLSX.writeFile(wb, exportFileName)
}
With this code only some files are written I guess because the for loop doesn't wait for the file to be written before continuing.
So I am trying to write each file within a promise like below:
Promise.all(
dataSetDivided.map((exportSet, i) => {
return new Promise((resolve, reject) => {
console.log(exportSet)
let ws = XLSX.utils.json_to_sheet(exportSet, {header: finalHeaders})
let wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
let todayDate = this.returnFormattedDate()
let originalFileName = this.state.fileName
let exportFileName = 'import_' + originalFileName + '_' + todayDate + '(part_' + (i + 1) + ').csv'
XLSX.writeFile(wb, exportFileName, (err) => {
if (err) {
console.log(err)
reject(err)
} else {
console.log('Created ' + exportFileName)
resolve()
}
})
})
})
)
.then(() => {
console.log('Created multiple files successfully')
})
.catch((err) => {
console.log('ERROR: ' + err)
})
But... this isn't working, again only some files are written and nothing is logged to the console. Can anyone give me any ideas how to make this work or a better way to achieve the goal of writing multiple files like this? There is a XLSX.writeFileAsync method but I can't find any examples of how it works and I'm not sure if that is what I need.
With thanks,
James
UPDATE:
I am now using setTimeout to delay the next writeFile call... this is working for my test cases but I am aware it isn't a good solution, would be much better to have a callback when the file is successfully written:
writeFileToDisk(dataSetDivided, i) {
if (dataSetDivided.length > 0) {
let exportSet = dataSetDivided[0]
let ws = XLSX.utils.json_to_sheet(exportSet, {header: finalHeaders})
let wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
let todayDate = this.returnFormattedDate()
let originalFileName = this.state.fileName
let exportFileName = 'import_' + originalFileName + '_' + todayDate + '(part_' + i + ').csv'
XLSX.writeFile(wb, exportFileName)
dataSetDivided.splice(0, 1)
i += 1
setTimeout(() => {this.writeFileToDisk(dataSetDivided, i)}, 2500)
}
}
this.writeFileToDisk(dataSetDivided, 1)
Any suggestions how to get this working without simulating the file write time would be much appreciated.
I just tried this (first time) XLSX code and can confirm that it writes the expected workbooks and runs synchronously...
'use strict'
const XLSX = require('xlsx');
let finalHeaders = ['colA', 'colB', 'colC'];
let data = [
[ { colA: 1, colB: 2, colC: 3 }, { colA: 4, colB: 5, colC: 6 }, { colA: 7, colB: 8, colC: 9 } ],
[ { colA:11, colB:12, colC:13 }, { colA:14, colB:15, colC:16 }, { colA:17, colB:18, colC:19 } ],
[ { colA:21, colB:22, colC:23 }, { colA:24, colB:25, colC:26 }, { colA:27, colB:28, colC:29 } ]
];
data.forEach((array, i) => {
let ws = XLSX.utils.json_to_sheet(array, {header: finalHeaders});
let wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
let exportFileName = `workbook_${i}.xls`;
XLSX.writeFile(wb, exportFileName)
});
Running this yields workbook_0.xls, workbook_1.xls, and workbook_2.xls, each with a single sheet entitled "SheetJS". They all look good in excel, for example, workbook_0 has...
I think you should do the writing asynchronously, and would suggest the following adaptation of the above ...
function writeFileQ(workbook, filename) {
return new Promise((resolve, reject) => {
// the interface wasn't clearly documented, but this reasonable guess worked...
XLSX.writeFileAsync(filename, workbook, (error, result) => {
(error)? reject(error) : resolve(result);
})
})
}
let promises = data.map((array, i) => {
let ws = XLSX.utils.json_to_sheet(array, {header: finalHeaders});
let wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
let exportFileName = `workbook_${i}.xls`;
return writeFileQ(wb, exportFileName)
});
Promise.all(promises).then(result => console.log(result)).catch(error => console.log(error));
Running this async code, I found that it produced the same expected results and did so asynchronously.
So your original loop looks right, and should work synchronously. The fact that you aren't getting expected results must be caused by something apart from timing (or maybe some timing issue induced by react?).
In any event, if you do want to use the async approach, which I highly recommend, I've shown how to do that (but I worry that might not fully solve the problem unless you sort out what's happening with your first attempt).
XLSX.writeFileAsync does have a callback with the following syntax.
xlsx.writeFileAsync(workbookName, workbook, (err) => {
// It's a callback
});
But this will handle only writing one file asynchronously.
Your case is typical, if you want to do a series things in which each item is asynchronous, then you should not just use iterative methods like loops/map/forEach.
One best library I would suggest for this is 'async'.
'async.parallel' function which takes a array of functions which execute asynchronously and calls callback after all of them finished.
https://caolan.github.io/async/docs.html#parallel
If the concern is to use the library asynchronously for not blocking the server, you should know that this library implementation seems to be synchronous and you should check out the library's server demos README since it has several proposals to workaround this problem: https://github.com/SheetJS/sheetjs/tree/master/demos/server

Categories

Resources