I am calling a third-party API via Axios async-await, and returning the result to a flutter application via a google cloud function. I am forced to use functions.https.onCall
because flutter can't call onRequest
functions as far as I know.
The result is shown correctly in console.log
in the logs of the cloud function but when the flutter app calls the function, it's always receiving null
. Why?
getSmsBalance: functions.https.onCall(async (data, context) => {
const business_id = data.business_id;
const collectionRef = db.collection("buser_sms");
const snapshot = await collectionRef.where("id", "==", business_id).get();
if (snapshot.empty) {
console.log("No matching documents - getSMSBalance .");
let response = {
status: false,
};
return JSON.stringify(response);
}
snapshot.forEach((doc) => {
if (
doc.data().enableReservationSms == true ||
doc.data().enableAutoReminder == true ||
doc.data().enableReminderSms == true
) {
// get balance
(async () => {
const balance = await getBalance(
doc.data().senderId,
doc.data().username,
doc.data().password
)
.then((result) => {
let response = {
status: true,
data: result,
};
console.log("balance is " result);
return JSON.stringify(response);
})
.catch((err) => {
console.error(`Error - getSmsBalance - ${err}`);
let response = {
status: false,
};
return JSON.stringify(response);
});
})();
}
});
}),
CodePudding user response:
There are several issues with your code:
- You are using async/await syntax inside an
Array.forEach
which does not allow to await because of its intrinsic design. If you want to use async/await within the loop iterations, you need to useArray.map
for example. But in most cases, you shouldn't use async/await inside a loop because it removes the advantages of asynchronous code execution (each iteration is only triggered after the previous one). - You don't return anything from your function, except in the case of
snapshot.empty
. Thereturn
s in thethen
andcatch
callbacks only assign the values to the variablebalance
which isn't used afterwards.
So in conclusion, you need to use something like:
return Promise.all(
snapshot.docs.map(function (doc) {
return getBalance(
doc.data().senderId,
doc.data().username,
doc.data().password
)
.then((result) => {
let response = {
status: true,
data: result,
};
console.log('balance is ' result);
return JSON.stringify(response);
})
.catch((err) => {
console.error(`Error - getSmsBalance - ${err}`);
let response = {
status: false,
};
return JSON.stringify(response);
});
})
);
Note that I'm providing that code snipped without any consideration for what format you actually need as the output. Having an array of response
s may not be what you need. But you should be able to adapt that code to what you need in the end.