Llamo a una API de terceros a través de Axios async-await y devuelvo el resultado a una aplicación flutter a través de una función de nube de Google. Me veo obligado a usar functions.https.onCall
porque flutter no puede llamar a las funciones onRequest
hasta donde yo sé.
El resultado se muestra correctamente en console.log
en los registros de la función en la nube, pero cuando la aplicación flutter llama a la función, siempre recibe null
. ¿Por qué?
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); }); })(); } }); }),
Hay varios problemas con su código:
Array.forEach
que no permite esperar debido a su diseño intrínseco. Si desea usar async/await dentro de las iteraciones de bucle, debe usar Array.map
por ejemplo. Pero en la mayoría de los casos, no debe usar async/await dentro de un bucle porque elimina las ventajas de la ejecución de código asíncrono (cada iteración solo se activa después de la anterior).snapshot.empty
. Los return
s en las devoluciones de llamada then
y catch
solo asignan los valores al balance
variable que no se usa después.Entonces, en conclusión, necesitas usar algo como:
return Promise.all( snapshot.map((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); }); }) );
Tenga en cuenta que estoy proporcionando ese código cortado sin tener en cuenta qué formato necesita realmente como salida. Tener una matriz de response
puede no ser lo que necesita. Pero debería poder adaptar ese código a lo que necesita al final.