firebase 理论上会不会过早退出?

gab6jxml  于 2023-04-13  发布在  其他
关注(0)|答案(1)|浏览(149)

函数是否有可能在文档更新之前退出/关闭,因此文档不会更新?代码中的更多注解:

exports.enterToWin = functions.https.onCall(async (data) => {
  const { user } = data;

  try {
    return await db.runTransaction(async (t) => {
      const ref = db.collection(COLLECTION_NAME);
      const snap = await ref.where('available', '==', true).get();
      const prize = snap.docs[i];

      // See how we're updating the prize here...
      t.update(prize.ref, {
        winner: user,
        available: false
      });

      // ... but we're not waiting for the transaction to complete before returning?
      // Could this cause the update to fail, in theory?
      return { uid: doc.id, ...doc.data() };
    });
  } catch (error) {
    return { error: 'Unexpected error: ' + error.message };
  }
});

像这样等待会更安全/更好吗?

await t.update(prize.ref, {
  winner: user,
  available: false
});

return { uid: doc.id, ...doc.data() };

函数在99%的时间里都很好。但是我们在生产中遇到了一些问题。一些用户获得了奖品,但是奖品后来似乎消失了。正在尝试解决实际发生的问题。谢谢

ej83mcc0

ej83mcc01#

JavaScript异步函数必须等待,否则在云函数终止之前,promise完全有可能无法解析。这在Firebase文档Sync, async, and promises中有详细说明:
管理函数的生命周期以确保其正确解析非常重要。通过正确终止函数,您可以避免因函数运行时间过长或无限循环而产生的过多费用。此外,您可以确保运行您的函数的Cloud Functions示例在您的函数成功达到其终止条件或状态之前不会关闭。
使用以下推荐的方法来管理函数的生命周期:

  • 通过返回JavaScript promise来解析执行异步处理的函数(也称为“后台函数”)。

这在Cloud Functions的Node.js运行时文档中有进一步的详细说明:
当处理涉及回调或Promise对象的异步任务时,必须显式通知运行时函数已完成这些任务的执行。可以通过几种不同的方式来完成此操作,如下面的示例所示。关键是代码必须等待异步任务或Promise完成后才返回;否则,函数的异步组件可能会在完成之前终止。
在Cloud Functions的提示和技巧文档中:

不启动后台活动

后台活动是在函数终止后发生的任何事情。一旦函数返回或以其他方式发出完成信号,函数调用就会完成,例如通过调用Node.js事件驱动函数中的callback参数。在优雅终止后运行的任何代码都无法访问CPU,也不会有任何进展。
要直接回答您的问题,您必须使用await调用update(),因为它是一个异步函数。您应该配置IDE和/或linter以检查未等待的异步函数,例如使用require-await
此规则警告没有await表达式的异步函数。
此规则的错误代码示例:

/*eslint require-await: "error"*/

async function foo() {
    doSomething();
}

bar(async () => {
    doSomething();
});

此规则的正确代码示例:

/*eslint require-await: "error"*/

async function foo() {
    await doSomething();
}

bar(async () => {
    await doSomething();
});

function foo() {
    doSomething();
}

bar(() => {
    doSomething();
});

// Allow empty functions.
async function noop() {}

相关问题