I have a function that is supposed to return a user's email from using the Firebase admin API getUser(uid) function,
function getEmail(uid){
var email;
admin.auth().getUser(uid)
.then((userRecord) => {
return userRecord.email;
})
.catch((error) => {
console.log('Error fetching user data:', error);
});
}
But in my other function when I make a variable that calls the function,
email = getEmail(uid);
the value in email is undefined, because the getUser function has returned a promise. How do I make the function getEmail wait to get the value of userRecord before returning?
I've tried adding await statements in different parts of the function but I'm not sure how to do it correctly. I'm a beginner in using the Google API.
Return the Promise that you get from admin.auth().getUser(uid) in your getEmail function.
function getEmail(uid) {
return admin.auth().getUser(uid)
.then((userRecord) => {
return userRecord.email;
})
.catch((error) => {
console.log('Error fetching user data:', error);
});
}
Then either use the returned Promise to chain a then callback.
getEmail(uid).then(email => {
console.log(email);
});
Or await it in an async function.
async function main() {
const email = await getEmail(uid);
console.log(email);
}
main();
Edit
As you explained in your comment below:
basically, I just want the code to run as if it were all synchronous/ line-by-line.
It's impossible to make asynchronous code synchronous, but it is possible to make it run line-by-line with async / await syntax. Promises that are being awaited in an async function will run line by line as you're telling the code to wait for it to resolve before going to the next line.
I've modified the code from your CodePen to include the aforementioned syntax. We're still using the same getEmail function that returns the promise from admin.auth().getUser(uid) and just wait for it to finish before doing something with the result.
function getEmail(uid) {
return admin.auth().getUser(uid)
.then((userRecord) => {
return userRecord.email;
})
.catch((error) => {
console.log('Error fetching user data:', error);
});
}
app.post("/sendx", async (req, res) => {
const uid = req.body.x.user.uid;
const email = await getEmail(uid);
let verified = false;
/*console.log(email.substring(email.indexOf('#')));
if (email.substring(email.indexOf('#')) == "#xxx.edu") {
verified = true;
}*/
res.send({ verified });
});
I hope this clears it up.
Related
This code does not execute the promise of testAuthentication or pinFileToIPFS and i am curious if this is a node concept i am not familiar of.
function uploadToPinata(filename) {
const pinata = pinataSDK(process.env.PINATA_KEY, process.env.PINATA_SECRET_KEY);
pinata.testAuthentication().then((result) => {
//handle successful authentication here
console.log(result);
}).catch((err) => {
//handle error here
console.log(err);
});
const readableStreamForFile = fs.createReadStream(filename);
const options = {
pinataMetadata: {
name: "NYC_NFT_TESTING",
},
pinataOptions: {
cidVersion: 0
}
};
pinata.pinFileToIPFS(readableStreamForFile, options).then((result) => {
//handle results here
console.log(result);
}).catch((err) => {
//handle error here
console.log(err);
});
}
is there a problem with this code using a promise within a function? I attemped to make the function async but that did not help. This code works just fine outside of a function but not within one.
"does not execute the promise": this is a strange phrase. Promises are objects. They don't execute -- they are created. And your function really creates them. However, it does not do much when these promises are resolved.
The problem is that uploadToPinata will execute all of the synchronous code and return. But then there are still a promises pending. Although you have console.log that will be executed once the relevant promise has resolved, there is no signal to the caller of uploadToPinata that these promises have resolved.
It is probably easiest to use async and await:
async function uploadToPinata(filename) {
const pinata = pinataSDK(process.env.PINATA_KEY, process.env.PINATA_SECRET_KEY);
const result = await pinata.testAuthentication();
//handle successful authentication here
console.log("authentication result", result);
const readableStreamForFile = fs.createReadStream(filename);
const options = {
pinataMetadata: { name: "NYC_NFT_TESTING" },
pinataOptions: { cidVersion: 0 }
};
const result2 = await pinata.pinFileToIPFS(readableStreamForFile, options);
//handle results here
console.log("pinFileToIPFS result", result2);
}
The caller of this function will now receive a promise, so it should probably want to do something when that promise has resolved:
uploadToPinata(filename).then(() => {
console.log("authentication and file operation done")
}).catch(error => console.log("error", error));
Summary: creating my own API that returns epoch time, and it involves using an express.js server, but it's running res.send() before the function call. I referenced this page, but it didn't help. Here's what I have:
app.get('/timestampAPI', async (req, res,) => {
try {
let finalResult = await getTimeStamp();
res.send({ something: finalResult });
} catch (error) {
console.log(error);
}
});
It'll start to run the function getTimeStamp(), and before that function finishes, it runs the res.send() function which shows up as '{}' because finalResult doesn't have a value. getTimeStamp() is an async function. I'm unsure of what I'm doing wrong.
Edit:
getTimeStamp() function:
async function getTimeStamp() {
await axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
.then(response => {
// also used console.log(response.data.UnixTimeStamp), which returns the timestamp
return response.data;
})
.catch(error => {
var errorMessage = error.response.statusText;
console.log(errorMessage);
});
}
Another edit: yes, the API referenced above does return the current epoch time, but CORS is blocking my other site from accessing it directly, so I can't use it on that site, which is why I'm using node.js for it so that I can allow myself to access it through my node.js program. Couldn't think of another way
returning value of the then method does not return from getTimeStamp function you should write you code in resolve pattern or using await like below
try this, make sure you write correct field name in response object
async function getTimeStamp() {
try{
const res = await axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
return res.data
}catch(error){
throw error
}
As an alternative to Mohammad's answer you can also use returning getTimeStamp function's result as a promise and it can solve your problem.
async function getTimeStamp() {
return new Promise((resolve, reject) => {
axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
.then(response => {
// also used console.log(response.data.UnixTimeStamp), which returns the timestamp
resolve(response.data);
})
.catch(error => {
var errorMessage = error.response.statusText;
console.log(errorMessage);
reject(error);
});
})
}
Or you would also replace await with return in getTimeStamp function in your code if you don't want to return promise.(Which is not I recommend.). You should also throw the error in catch block which is generated in getTimeStamp function for catching the error in try-catch block that you use to call app.get(...).
I have three API calls which should be dependent on one another. The second API call should trigger only when the first succeeds.
With my current implementation, I'm getting a CORS error when the first API call is made and was able to catch the error in the catch block. However, I'm seeing that the second and third APIs calls are made irrespective of the error that got caught in the first API call.
Could anyone please advise?
const firstApiCall = async() => {
try {
await axios.post(
process.env.FIRST_API,
payload
);
]
} catch (err) {
console.log(`err`, err);
}
};
const secondApiCall = async() => {
try {
await axios.post(
process.env.SECOND_API,
payload
}
} catch (err) {
console.log(`err`, err);
}
};
const thirdApiCall = async() => {
try {
await axiosInstance.patch(
process.env.THIRD_API,
payload
);
} catch (err) {
console.log('err', err);
}
};
firstApiCall();
secondApiCall();
thirdApiCall();
You're calling the functions synchronously when you need to do it asynchronously:
async function performTasks() {
await firstApiCall();
await secondApiCall();
await thirdApiCall();
}
performTasks();
You can use the ES6 Promise implementation approacg. Therefore you should take a look to this ressource : [Promise][1]
With the promise approach you can react at each step / each API call.
[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
async await functions work only in their local scope.
For example:
const myFunc = async() => {
try{
//...
await foo();
//All the code below will be blocked till
//the promise return by foo function is resolved
}
catch{
//...
}
}
const main = () => {
myFunc();
otherFunc();
//Other function calls
//Regardless of using async await in myFunc,
//the code bellow myFunc will be executed as
//async await will work only in myFunc block scope
}
main()
What you can do is, use async await inside the main function, so that the functions would be called in an order
const main = async () => {
await myFunc();
await otherFunc();
}
i am trying to call an async function inside a class but keep getting an error that this.getcategory.then is not a function
at category.js:21
I have a form which is used by the admin to add more categories into the database. categform.addEventListener('submit', e => { this line will listen for the submit event after which the data is taken and inserted into the the database using the code using the code snippet below
super.postText("../includes/getcategoy.inc.php", categformData)
.then(res => {
console.log(res);
// 1. if the results are ok fetch the fresh data from the database
this.getcategory.then(
res => {
console.log(res);
}
)
}).catch((error) => {
console.error('Error:', error);
});
now the above code returns a promise then if the result is ok i call another function in the same class got get the latest data form the database. the fuction is this.getcategory remember i am calling the function inside the then and am getting an error. the reason why i am calling inside the then is because only want it to be executed after sending of the data into the database has been resolved.
but when i call it outside the first function i do not get an error..
if you look just after the catch block i have commented it out. if i call it there i do not get an error. yet i do not want to call it there. remember the function returns a promise and it is defined as the last function in the class
how can i solve this problem, below is the whole code
import { FETCH } from "./fetch.js";
class CATEGORY extends FETCH {
constructor() {
super()
}
listencategory() {
//1. Listen for the button click
const categform = document.getElementById('categotyform');
categform.addEventListener('submit', e => {
e.preventDefault();
//2. get the data from form
const categformData = new FormData(categform);
super.postText("../includes/getcategoy.inc.php", categformData)
.then(res => {
// console.log(res);
// 1. if the results are ok fetch the fresh data from the database
this.getcategory.then(
res => {
console.log(res);
}
)
}).catch((error) => {
console.error('Error:', error);
});
});
//this.getcategory().then(res=>{
// console.log(res);
//
//})
}
async getcategory() {
try {
const results = await super.get("../includes/getcategoy.inc.php");
return results;
} catch (error) {
console.log(error);
}
}
}
const categ = new CATEGORY;
categ.listencategory();
i am trying to get data that has been returned by async getcategory()
getcategory is an Async function that should be made a function call like below.
this.getcategory().then(
res => {
console.log(res);
}
)
This link helps you create and use promises effectively.
Async functions - making promises friendly
Take the following contrived example:
const housekeepingStuff = async function (data) {
const result = await notImportant(data);
result.more = 'yawn';
storeInDatabase(result);
};
const getStuff = async function () {
try {
const data = await getData();
data.extra = 'wow';
housekeepingStuff(data); // <---- don't want to await... but need to for error catching
return Promise.resolve(data);
} catch (err) {
return Promise.reject(err);
}
};
try {
const myData = await doSomeStuff();
res.send(myData);
} catch (err) {
console.log(err);
res.sendStatus(400);
}
I want to return the data from getStuff () ASAP without waiting for housekeepingStuff() but if I don't await that function then I have an uncaught error.
I could call housekeepingStuff() outside the getStuff() function, after getting and sending the data to whoever wants it:
try {
const myData = await doSomeStuff();
res.send(myData);
await housekeepingStuff(data); // <---- am awaiting but who cares because nothing follows
} catch (err) {
console.log(err);
res.sendStatus(400);
}
But that doesn't seem right because I don't want to have to remember to call housekeepingStuff() every time I call doSomeStuff()... it should ideally be handled "internally".
What is the correct approach here?
A promise (or async) function has 2 possible outcomes:
A successful outcome
An error outcome
To get either outcome, you must wait for it. You can't wait for 1 condition and not for the other, because the entire thing needs to execute so you can find out what the outcome was.
Otherwise you're really asking the javascript engine: Please predict for me if the function will fail, and if it does, await it.
The correct approach therefore is to just await it.
However, if you don't care about either successful or failed outcomes of this function, just call the function via another async function that eats all the errors:
async function doSomeStuffAndIgnoreError() {
try {
await doSomeStuff();
} catch (e) {
console.error(e);
}
}