How to use multiple async/await functions? - javascript

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.

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

working with Node js Await/Async functions

This is my axios Request to call the API.
export function axiosGet (url) {
return opsutils.get(url)
.then(function (response) {
return response.data.data;
})
.catch(function (error) {
return 'An error occured..' + error;
})
}
From here i'm calling it asynchrously
async getDirList(data){
this.domainDir=data.domain_name
var apiurl="some URL"
var stat = await axiosGet(apiurl)
if (status){
this.domainlog= stat
}
From here i'm calling the async func defined above
Notify(data){
var filelist = this.getDirList(data)
if(filelist){
var status = createNotification(data.domain_name,message_stripped,'Degrading web server performance')
}
The ideal should be like this that it should go forward only after the promise is resolved ,right now the var filelist got empty.
How do i get to solve this problem ?Thanks in advance
The problem is this.getDirList(data) is not being accessed asynchronously as well. Remember, because that is async now, it's returning a promise, so you either need to chain it with .then():
Notify(data){
var filelist = this.getDirList(data)
.then(data => {
var status = createNotification(data.domain_name,message_stripped,'Degrading web server performance')
});
}
Or turn Notify() into an async function as well:
async Notify(data){
var filelist = await this.getDirList(data);
if(filelist){
var status = createNotification(data.domain_name,message_stripped,'Degrading web server performance')
}
Additionally, make sure you're actually returning data from getDirList so you can utilize the return value when you await it.

Stuck in asnyc/await

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

What's wrong with this async function?

async lsEntered(){
if(this.service.wd == '')
{
await basic((this.service.wd));
}
else
{
await basic(('/'+this.service.wd));
}
this.files = await JSON.parse(localStorage.getItem('FILENAMES'));
var filesList = document.getElementById(this.trackLine.toString());
var li;
for (var i = 0; i < this.files.length; i++) {
li = document.createElement('li');
li.appendChild(document.createTextNode(this.files[i].name));
filesList.appendChild(li);
}
localStorage.clear();
}
I want to wait until basic is finished and JSON.parse finishes before displaying the values in the DOM. I'm getting the values of the previous call every time which is tell me the async is no working. To be fair I don't have tons of TS experience.
Edit: This is basic I was hoping not to have to deal with it as it's a javascript function and fragily integrated into this app.
var basic = function (path) {
var ACCESS_TOKEN = '';
var dbx = new Dropbox({ accessToken: ACCESS_TOKEN });
dbx.filesListFolder({ path: path })
.then(function (response) {
localStorage.setItem('FILENAMES',JSON.stringify(response.entries));
console.log(response);
})
.catch(function (error) {
console.error(error);
});
return false;
}
let myPromise = new Promise((resolve, reject) => {
// Work you want to execute
resolve("I am done");
});
myPromise.then((successMessage) => {
// successMessage is whatever we passed in the resolve(...) function above.
console.log("Yay! " + successMessage);
});
You can only await promises1 and basic is not returning a promise. You need to do
return dbx.filesListfolder(...)...
Also consider what Bergi said in their comment.
1: Actually, you can await any value, but there is no point in awaiting something that is not a promise. By not returning the promise from basic, lsEntered won't wait for the local storage to be set.

Optional callback not being called in the node.js async module's forEachOf method

I'm using the async module's forEachOf method to print the end result after iterating through an object. Here is a shortened version of what I'm doing:
var async = require('async'),
cheerio = require('cheerio'),
request = require('request');
var returnArray = [];
async.forEachOf(myObj, function (value, key, callback) {
var anotherObj = {};
anotherObj.type = "val1";
request(someurl, function(err, res, body) {
if (err) {
return callback(err);
}
var $ = cheerio.load(body);
anotherObj.name = "val2";
var miniObj = {};
$('#some-element', "#an-id").each(function(i, value) {
var val = value.value;
miniObj[size] = val;
});
anotherObj.miniObj = miniObj;
returnArray.push(anotherObj);
return callback();
});
}, function (err) {
if (err) {
console.error(err.message);
}
console.log(returnArray);
});
However, when I run the program, nothing (namely, 'returnArray') gets printed to the console like it should be.
For reference, I have looked at these other, similar posts:
Using async module to fire a callback once all files are read (seems outdated, is using the wrong method, and doesn't address the issue)
Last callback not being called using async (doesn't address the issue)
I'm not sure what I'm doing wrong here. Could anyone please point out what I'm doing wrong?
Thanks!
EDIT: So I think I finally figured out what I was doing wrong. In a different example I provided earlier HERE, using Runnable I forgot to add a 'return callback()' statement. Then it worked. The only difference between that and this example being that my 'return callback()' statement in the above-provided example is itself called within another asynchronous method. I think in order to fix my problem I will somehow have to make sure (probably using some control flow function in async's library) to call 'return callback()' at the correct 'scope/level' after the second asynchronous method has finished. I think I will attribute this, my mistake, to the lack of documentation on proper usage of the 'return callback()' statement in the async docs. I will update this post with a solution once I figure it out (and catch up on some sleep)!
Your statement:
if (err) {
return callback(err);
}
is not valid for asynchronous programming. Instead, you should do:
if(err) callback(err);
This is why you aren't getting anything returned. I rewrote your code with async concepts applied:
var async = require('async'),
var cheerio = require('cheerio'),
var request = require('request');
var returnArray = [];
async.forEachOf(myObj, function (value, key, next) {
var anotherObj = {};
anotherObj.type = "val1";
request(someurl, function(err, res, body) {
if (err) next(err);
var $ = cheerio.load(body);
anotherObj.name = "val2";
var miniObj = {};
async.each($('#some-element', "#an-id"), function (value, next) {
var val = value.value;
miniObj[size] = val;
});
anotherObj.miniObj = miniObj;
returnArray.push(anotherObj);
next();
});
}, function (err) {
if (err) console.error(err.message);
console.log(returnArray);
callback(returnArray);
});
Notice that you have two different named callbacks. The outer function callback is called callback. The inner function callback is called next.

Categories