Stuck in asnyc/await - javascript

Searched on many places and also went through many tutorials to deeply understand the async/awiat behavior of the javascript. Here is my code:
var bookAppointment = async (data) => {
return User.findOne({_id: data.user_id})
.then((userfound) =>{
//manipulate user's data and find if in array the specific object exist
var found = await userfound.dataArray.find( function(element){
return element.data == data.user_data
});
//here I want to wait until above result comes to evaulate below condition
if(found)
{
return "Sorry! data does not exist";
}
else
{
return userfound;
}
})
.catch(err => {
return err
});
}
What I want to achieve is to make my if else condition to wait above find function on array of javascript. Here is the error I'm facing:
SyntaxError: await is only valid in async function
I'm unable to understand where I'm wrong! Even my function has keyword async with its definition. Anyone around for a quick help?

At (userfound) =>{...} you're scoping another function.
For await to work, you need it to be something like async (userfound) => {...}

Catch and Then keyword are not used is async/await functions.
var bookAppointment = async (data) => {
var found = await User.findOne({_id: data.user_id});
try {
//do here like in then
} catch (e) {
//error handling
}
}

Related

How do I organize my javascript code instead of nesting callbacks?

I'm making a application in javascript (Nodejs), I'm kinda new to it. My code needs to do multiple congruent requests, I organized my code in async functions so I can linearly call them
my first code looked like this
async function Fa(param,param1,callback,error){
//SOME CODE
}
async function Fb(param){
//SOME CODE
}
async function Fc(param){
//SOME CODE
}
function Fd(param,callback,error){
//SOME CODE
}
and use it like this
Fa(param,param1,
(result,result1) => {
Fb(resultB) => {
Fc(resultB);
}
},
(error) => { /*handle error*/ }
);
Fd(param,
(result)=>{
//handle result
},
(error)=>{
//handle error
}
)
of course this is not the right way to go for me...
so I got creative and wrote this
async function Fa(param,param1){
var errorFun,resultFun;
function setOnError(error){errorFun = error;}
function setOnResult(result){resultFun = result;}
async function execute(){
//SOME CODE HERE
}
return {setOnError,setOneResult,execute}
//I had to write a execute function because `Fa` being an async function I couldn't access setError and other inner functions from outside
}
I'm not repeating all the functions but I hope you got the idea
so my code looks like this
var resultA,resultA1;
var fa = await Fa(param,param1);
fa.setOnError((error) => /*handle error*/ );
//I want to terminate my code here (all this being in a function) but I don't know how to do so because I can't even set a flag to understand if error function has been called because I have multiple function with error and setting multiple flags would be stupid
fa.setOnResult( (result,result1) => {resultA = result; resultA1 = result1} );
await fa.execute()
var fb = await Fb(param);
fb.setOnResult((result) => {Fc(result);})
await fb.execute();
var fd = await Fd(param);
fd.setOnResult(/*some code*/);
fd.setOnError(/*some code*/);
await fd.execute();
I like my second version more but I don't know how to handle the errror (I want to stop executing the main function) and I think it's a bit overkill..
Any suggestion will be appreciated, thank you
you can try this code.
if execute function throw an error, it will be caught by the try-catch block in the main function
async function Fa(param, param1) {
var errorFun, resultFun;
function setOnError(error) { errorFun = error; }
function setOnResult(result) { resultFun = result; }
async function execute() {
//SOME CODE HERE
if (error) {
throw new Error(error);
}
}
return { setOnError, setOnResult, execute }
}
async function main() {
try {
var fa = await Fa(param, param1);
fa.setOnError((error) => /*handle error*/ );
fa.setOnResult((result, result1) => { resultA = result; resultA1 = result1 });
await fa.execute();
var fb = await Fb(param);
fb.setOnResult((result) => { Fc(result); });
await fb.execute();
var fd = await Fd(param);
fd.setOnResult(/*some code*/);
fd.setOnError(/*some code*/);
await fd.execute();
} catch (error) {
// handle error
}
}

function stops when fetch() fails

so I have a normal thing you would do to find if a file exists and proceed accordingly:
let response = await fetch(url);
if (response.ok) {
//it exists
} else {
//it doesn't
}
Problem is, of course, if it fails it gives me a TypeError: Failed to fetch and my function stops.
Is there a way I can suppress the error?
I cannot change from a fetch function, i've tried everything else and fetch is the best option in my context.
Thanks in advance.
You will need to implement try and catch and it is quite easy to implement it. You can have a look at Try and Catch Documentation
Have a look at the sample code below
try {
let response = await fetch(url);
}
catch(err) {
alert("Error Message : " + err.message);
}
Is there a way I can suppress the error?
You should wrap your function that may cause the error in try...catch.
const fetch = (isFine) => new Promise(resolve => {
if(isFine)
resolve("Normal data");
else
throw new Error("Error msg...!");
});
const myFunction = async (isFine) => {
try {
const response = await fetch(isFine);
console.log(response);
}
catch(err) {
console.log("Oops..." + err.message);
}
}
myFunction(true);
myFunction(false);

How to use multiple async/await functions?

I have an error when I deploy my functions : error Parsing error: Unexpected token saveLastReview.
I need to get some document values, then call a url request, then set data in my document.
async function getValue() {
try {
var doc = await admin.firestore().collection('mycollec').doc('mydoc').get();
var data = doc.data()
return data;
} catch(e) {
console.log(e);
return null;
}
}
async function saveLastReview(authorName) {
var rating = "4";
var title = "my title";
var content = "my content";
let data = {
rating : rating,
title: title,
content: content
};
try {
var doc = await admin.firestore().collection('mycollec').doc('mydoc').collection('reviews').doc(authorName).set(data);
return doc;
} catch(e) {
console.log(e);
return null;
}
}
app.get('/hello-world', async(req, res) => {
var data = await getValue();
if (data === null) {
request("https://itunes.apple.com/gb/rss/customerreviews/id=284882215/sortBy=mostRecent/json", function (error, response, body) {
//code to get authorname from the response
var result = await saveLastReview(authorname);
//check if doc was set correctly
//do something
})
}
return res.status(200).send("sent !");
});
module.exports.app = functions.https.onRequest(app);
I'm not very familiar with async/await. I don't find the problem.
It looks like your callback in the request is missing the async keyword. Might lead to the error you are seeing, which relates to the line where you await, which means nothing in a non-async function.
Should probably be :
//...
request("https://itunes.apple.com/...", async function (error, response, body) {
//...
EDIT: as mentioned in the comment, that is maybe not it. But I also notice that saveLastReview is an async function itself, and I don't know how async function behave when they are awaited. Maybe another avenue of investigation if what I mentioned first doesn't fix the issue.

async/await not working and i dont see why

function projectHTML(e) {
let proj = await getProject(e.srcElement.dataset.id);
console.log(proj);
return `
<div id="Project">
<h1>${proj.name}</h1>
<p>Description: ${proj.description}</p>
</div>
`;
}
async function getProject(id) {
try {
let res = await fetch(`http://127.0.0.1:5000/api/projects/${id}`);
res = await res.json();
return res;
} catch (e) {
console.error(e);
}
}
The first function, projectHTML(), is being called from another file. I am able to return the value from function gethelp(), ProjectsHTML(). I can even log it in the console and indeed see it's correct. However, it won't load up into the template literal that I have. Please, someone lend a hand. I tried doing async...await in try blocks in ProjectsHTML() and still no luck.
Image of web issue
Function
async function getProject(id) {
try {
const res = await fetch(`http://127.0.0.1:5000/api/projects/${id}`);
return res.json();
} catch (e) {
console.error(e);
}
}
Call
getProject(id).then((data) => {
console.log(data)
})
You need to modify your code like following:
async function projectHTML(e) {
let proj = await getProject(e.srcElement.dataset.id);
console.log(proj)
return `<div id="Project">
<h1>${proj.name}</h1>
<p>Description: ${proj.description}</p>
</div>`;
};
If I am not wrong above function is an event handler and you are using passing it in your html. If not, and you are calling it from another function, you need to use awaitwhile calling this function:
await projectHtml(e)
Let me know if this helps.

await Promises.all SyntaxError

According to this article: https://medium.com/#bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8
It seems like it could be possible to use below syntax:
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
for multiple promises execution. However while using it I get Uncaught SyntaxError: Unexpected identifier.
How can i use async/await and promise.all to achieve multiple simultaneous operations executed and one resolve with a response.
-----EDITED
the function i am using inside promise.all is this one:
async function getJson(callback) {
try {
let response = await fetch('URL_LINK_HERE');
let json = await response.json();
return json;
} catch(e) {
console.log('Error!', e);
}
}
as a test field i am using google chrome Version 60.0.3112.113
Most likely your code looks something like this:
var thingsDone = await Promise.all([
Promise.resolve("eat"),
Promise.resolve("sleep")
]);
console.log(thingsDone);
This will not work because the await keyword is only valid within an async function (which the global context is not). It will simply cause a syntax error.
One way to handle this is to use it like a regular old promise and not using the await keyword:
Promise.all([
Promise.resolve("eat"),
Promise.resolve("sleep")
]).then((thingsDone) => console.log(thingsDone));
Or if you want to get fancy (or need more room to write an expressive function), wrap your logic in an async function and then handle it like a promise:
async function doThings() {
var eat = await Promise.resolve("eat");
var sleep = await Promise.resolve("sleep");
return Promise.all([Promise.resolve(eat), Promise.resolve(sleep)]);
}
doThings().then((thingsDone) => console.log(thingsDone));
This would allow you to use await as needed and is much more helpful in a more complicated function.
Or even more succinctly using an immediately-executing async function:
(async() => {
var eat = await Promise.resolve("eat");
var sleep = await Promise.resolve("sleep");
return Promise.all([Promise.resolve(eat), Promise.resolve(sleep)]);
})().then((thingsDone) => console.log(thingsDone));
torazaburo pointed me to right direction in his comments and i figured it out, this is the final code that is working:
var getJson = async function() {
try {
let response = await fetch('http://mysafeinfo.com/api/data?list=englishmonarchs&format=json');
let json = await response.json();
return json;
} catch(e) {
console.log('Error!', e);
}
}
var check_all = async function(callback) {
callback( [foo, bar] = await Promise.all([getJson(), getJson()]) );
};
check_all(function(data) {
console.log(data);
});
This works, example here: https://jsfiddle.net/01z0kdae/1/

Categories