index.ts :
import * as admin from "firebase-admin" import fetch, { Headers } from "node-fetch"; interface BarPayload { topic: string, token: string, } exports.bar = functions.https.onCall(async (data, context) => { if (data != null) { const payload: BarPayload = { topic: data.topic, token: data.token, } const url = `https://${location}-${project}.cloudfunctions.net/subscribeToTopic` await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ topic: payload.topic, token: payload.token, }), }) } return null; }); export const subscribeToTopic = functions.https.onRequest(async (req, res) => { const payload = req.body as BarPayload; fetch('https://iid.googleapis.com/iid/v1/' + payload.token + '/rel/topics/' + payload.topic, { method: 'POST', headers: new Headers({ 'Authorization': 'key=AA...Wp9', 'Content-Type': 'application/json' }) }).then(response => { if (response.status < 200 || response.status >= 400) { res.sendStatus(299) } }).catch(error => { console.error(error); res.sendStatus(299) }) return Promise.resolve(); }) Estoy ejecutando bar en Flutter y veo el error de tiempo de espera en Logs Explorer:
textPayload: "La ejecución de la función tomó 60051 ms. Finalizó con el estado: tiempo de espera"
Pero si cambio mi subscribeToTopic de la función HTTP a una función invocable, entonces funciona bien. Por ejemplo:
exports.subscribeToTopic = functions.https.onCall(async (data, context) => { fetch('https://iid.googleapis.com/iid/v1/' + data.token + '/rel/topics/' + data.topic, { method: 'POST', headers: new Headers({ 'Authorization': 'key=AA...Wp9', 'Content-Type': 'application/json' }) }).then(response => { if (response.status < 200 || response.status >= 400) { console.log('Error = ' + response.error); } }).catch(error => { console.error(error); }) return null; });(Sé que estoy cometiendo un error trivial, y soy nuevo en TypeScript. Cualquier ayuda sería apreciada :)
No debe return Promise.resolve(); en la función de nube HTTPS:
send() , redirect() o end() ;return Promise.resolve(); se ejecuta antes de que se complete la llamada asíncrona para buscar.Lo siguiente debería hacer el truco (no probado):
export const subscribeToTopic = functions.https.onRequest(async (req, res) => { try { const payload = req.body as BarPayload; const response = await fetch('https://iid.googleapis.com/iid/v1/' + payload.token + '/rel/topics/' + payload.topic, { method: 'POST', headers: new Headers({ 'Authorization': 'key=AA...Wp9', 'Content-Type': 'application/json' }) }); if(response.status < 200 || response.status >= 400) { res.status(299).send(); } } catch (error) { res.status(400).send(); } }) Sin embargo, no entiendo por qué separa su lógica comercial en dos funciones en la nube. ¿Por qué no obtiene directamente https://iid.googleapis.com dentro de la función Callable Cloud Function de la bar ?