Declaring Custom Exceptions to use with Firestore Callable Functions and VueJS - javascript

This far, I tried
A
class MyException extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
exports.MyException = MyException;
VueJS says "exports is not defined"
If I simply did
B
exports.MyException = () => {}
then Firebase says MyException is not a constructor. When I
throw new MyException()
Actually, once the exception is passed through callable functions, would it still be an instanceOf?
Should I just go with
C
try {
let d = await db.collection('x').document('y')
if (!d.exists) {
let e = new Error('Document Does not Exist')
e.code = 'ERR_NO_DOCUMENT'
throw e
}
else {
return d.data()
}
}
Is C a good practice?

As explained in the documentation for Callable Cloud Functions:
To ensure the client gets useful error details, return errors from a
callable by throwing (or returning a Promise rejected with) an
instance of functions.https.HttpsError.
So doing
try {
let d = await db.collection('x').document('y')
if (!d.exists) {
let e = new Error('Document Does not Exist')
e.code = 'ERR_NO_DOCUMENT'
throw e
}
else {
return d.data()
}
}
will not work.
You need to do, in your Callable Cloud Function, something like:
try {
let d = await db.collection('x').document('y')
if (!d.exists) {
let e = new Error('Document Does not Exist')
e.code = 'ERR_NO_DOCUMENT'
throw e
}
else {
return d.data()
}
} catch (error) {
throw new functions.https.HttpsError('internal', error.message);
}

Related

Cannot read property 'findIndex' of undefined bot

I am trying to put an option in a bot and I get the error when I run the command. !ddd is the command
obterInfoDDD: async(DDD)=>{
try {
const githubGistDDD= await axios.get(" here I put the github directory ddd.json")
const estados = githubGistDDD.data.estados
const indexDDD = estados.findIndex(estado => estado.ddd.includes(DDD))
if(indexDDD != -1){
var resposta = criarTexto(msgs_texto.utilidades.ddd.resposta, estados[indexDDD].nome, estados[indexDDD].regiao)
return resposta
} else {
throw new Error(msgs_texto.utilidades.ddd.nao_encontrado)
}
} catch(err){
var errors = [msgs_texto.utilidades.ddd.nao_encontrado]
if(!errors.includes(err.message)){
consoleErro(err.message, "API obterInfoDDD")
throw new Error(msgs_texto.utilidades.ddd.erro_servidor)
} else {
throw err
}
}
}

how to make if there is no file it will do nothing

hey so I'm trying to const some JSON
const cidc = require('./cid/cid.json')
const dc = require('./details/cid.json')
const lc = require('./lik/cid.json')
if(!cidc){
return
}else{
fs.unlinkSync('./src/main/setting/cid/cid.json')
} if(!dc) {
return
}else {
fs.unlinkSync('./src/main/setting/details/cid.json')
} if (!lc){
return
}else {
fs.unlinkSync('./src/main/setting/lik/cid.json')
}
so I'm trying to delete the dc file and it error
how can I make if there is no such file named that it will do nothing (aka return nothing)
and if there is a file named that it will const it to a variable
Since require throws an error of Error: Cannot find module ... and you don't catch those errors, your script will fail.
You could define a new require-function where you catch the error and return undefined:
function safeRequire(path) {
try {
return require(path);
} catch(err) {
return undefined;
}
}
Then use this function in your script:
const cidc = safeRequire('./cid/cid.json')
const dc = safeRequire('./details/cid.json')
const lc = safeRequire('./lik/cid.json')
// rest of your code
Also you can simplify your if/else conditions by inverting the condition:
if (cidc) {
fs.unlinkSync('./src/main/setting/cid/cid.json')
}
if (dc) {
fs.unlinkSync('./src/main/setting/details/cid.json')
}
if (lc){
fs.unlinkSync('./src/main/setting/lik/cid.json')
}
Alternatively you don't even need to use require at all, just check if the files exist using e.g. fs.access(...).
You could directly use unlink with try catch without any requires
function unlink(filePath) {
try {
fs.unlinkSync(filePath);
} catch (e) {
//ignore
}
}
unlink('./src/main/setting/cid/cid.json')
unlink('./src/main/setting/details/cid.json')
unlink('./src/main/setting/lik/cid.json')

Something Wrong With My Asynchronous JavaScript Code

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
}
}
}

Cannot read property 'length' of undefined...Although the object is defined

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;
});

Throw statement in JavaScript gives "undefined undefined" output

Anytime I try using the throw statement in a try/catch command.
It gives me an output of undefined undefined.
Please how can I make it work.
Here is the code I used
try {
let a = prompt("Answer");
if (a == 10) {
throw "right";
} else {
throw "wrong"
}
} catch (i) {
alert(i.message);
}
You have multiple errors:
You have to convert the result to a number before the comparison, you can use the Number function.
You have to show the error and not only its message property since you are throwing a string and not an object.
try {
const a = Number(prompt('Answer'));
if (a === 10) {
throw 'right';
} else {
throw 'wrong';
}
} catch (e) {
alert(e);
}

Categories