You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Firebase云函数中使用Google Cloud Task Queue并获取JSON响应

Google Cloud Tasks实现任务结果回传的方案

Google Cloud Tasks本身是异步队列服务,创建任务时只会返回任务的元数据(如任务名称),不会直接返回任务的执行结果。要实现类似Redis队列的"任务完成后获取结果继续流程"的需求,需要自行设计结果存储+主动查询/回调通知的机制,以下是具体实现方案:

方案一:结果存储+主动轮询

通过Firebase Firestore(或Realtime Database)存储任务结果,发起任务的函数定期查询存储直到获取结果。

修改任务处理函数(addNumbersFunc)

执行计算后将结果存入Firestore,用唯一任务ID作为标识:

const { Firestore } = require('@google-cloud/firestore');
const firestore = new Firestore();

exports.addNumbersFunc = functions.https.onRequest(async (req, res) => {
  const payload = req.body;
  const taskId = payload.taskId;
  const answer = payload.numbers.a + payload.numbers.b;

  // 将结果写入Firestore
  await firestore.collection('taskResults').doc(taskId).set({
    answer: answer,
    status: 'completed',
    timestamp: new Date()
  });

  res.json({ answer: answer });
});

修改发起任务的函数(exampleFunction1)

生成唯一任务ID,创建任务后轮询Firestore获取结果:

const { v4: uuidv4 } = require('uuid');
const { Firestore } = require('@google-cloud/firestore');
const firestore = new Firestore();

exports.exampleFunction1 = functions.https.onCall(async (data) => {
  // 生成唯一任务ID
  const taskId = uuidv4();

  const jsonPayload = JSON.stringify({
    taskId: taskId,
    numbers: { a: 1, b: 2 }
  });

  const url = `https://${location}-${project}.cloudfunctions.net/addNumbersFunc`;

  const task = {
    httpRequest: {
      httpMethod: 'POST',
      url: url,
      headers: { 'Content-Type': 'application/json' },
      body: Buffer.from(jsonPayload).toString('base64')
    },
    oidcToken: { serviceAccountEmail }
  };

  const request = { parent: parent, task: task };
  const [response] = await client.createTask(request);
  console.log(`Created task ${response.name}`);

  // 轮询获取结果(最多等待30秒,每秒查询一次)
  const maxWaitTime = 30000;
  const pollInterval = 1000;
  let elapsedTime = 0;
  let taskResult = null;

  while (elapsedTime < maxWaitTime) {
    const doc = await firestore.collection('taskResults').doc(taskId).get();
    if (doc.exists) {
      taskResult = doc.data();
      break;
    }
    await new Promise(resolve => setTimeout(resolve, pollInterval));
    elapsedTime += pollInterval;
  }

  if (!taskResult) {
    throw new functions.https.HttpsError('deadline-exceeded', '任务执行超时');
  }

  // 可选:获取结果后删除存储记录
  await firestore.collection('taskResults').doc(taskId).delete();

  return {
    taskName: response.name,
    answer: taskResult.answer
  };
});

方案二:回调通知

任务处理完成后主动调用预设的回调URL,将结果传递回去,适合长时间运行的任务。

修改任务处理函数

执行完成后调用回调URL:

const axios = require('axios');

exports.addNumbersFunc = functions.https.onRequest(async (req, res) => {
  const payload = req.body;
  const answer = payload.numbers.a + payload.numbers.b;
  const callbackUrl = payload.callbackUrl;
  const taskId = payload.taskId;

  // 调用回调URL传递结果
  try {
    await axios.post(callbackUrl, {
      taskId: taskId,
      answer: answer
    });
  } catch (err) {
    console.error('回调失败:', err);
  }

  res.json({ answer: answer });
});

新增回调函数

接收处理函数的结果并存储(或直接通知发起方):

const { Firestore } = require('@google-cloud/firestore');
const firestore = new Firestore();

exports.taskCallback = functions.https.onRequest(async (req, res) => {
  const { taskId, answer } = req.body;
  await firestore.collection('taskResults').doc(taskId).set({
    answer: answer,
    status: 'completed'
  });
  res.status(200).send('回调已处理');
});

修改发起任务的函数

在Payload中加入回调URL和任务ID,之后可通过查询Firestore获取结果:

const { v4: uuidv4 } = require('uuid');
const { Firestore } = require('@google-cloud/firestore');
const firestore = new Firestore();

exports.exampleFunction1 = functions.https.onCall(async (data) => {
  const taskId = uuidv4();
  // 回调URL为新增的taskCallback函数地址
  const callbackUrl = `https://${location}-${project}.cloudfunctions.net/taskCallback`;

  const jsonPayload = JSON.stringify({
    taskId: taskId,
    numbers: { a: 1, b: 2 },
    callbackUrl: callbackUrl
  });

  const url = `https://${location}-${project}.cloudfunctions.net/addNumbersFunc`;

  const task = {
    httpRequest: {
      httpMethod: 'POST',
      url: url,
      headers: { 'Content-Type': 'application/json' },
      body: Buffer.from(jsonPayload).toString('base64')
    },
    oidcToken: { serviceAccountEmail }
  };

  const request = { parent: parent, task: task };
  const [response] = await client.createTask(request);
  console.log(`Created task ${response.name}`);

  // 此处可根据业务选择:
  // 1. 立即返回任务ID,让前端自行轮询结果
  // 2. 继续轮询Firestore直到获取结果(同方案一的轮询逻辑)
  return { taskName: response.name, taskId: taskId };
});

注意事项

  • 限流实现:Cloud Tasks本身支持通过队列配置(并发数、速率限制)实现HTTP接口的限流,无需额外代码处理。
  • 权限控制:确保只有授权的服务账号能写入taskResults集合,回调URL需验证请求来源(如通过OIDC令牌)防止恶意调用。
  • 超时与重试:根据任务实际执行时间调整轮询的超时时间,Cloud Tasks默认会重试失败的任务,需避免重复写入结果。

内容的提问来源于stack exchange,提问作者BillyRay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 17:35:30