Firebase 函数的异步初始化

Asynchronous initialization of Firebase Functions

我必须在我的函数启动时做一些异步工作,例如从 Google Secrets Manager 获取机密并根据这些机密初始化客户端对象。我应该如何构建我的代码,以便我的函数异步初始化并且可以在不等待初始化对象的情况下访问它们?

如果不 运行 进入竞争条件,则无法保证您的初始化已在您的函数被触发之前完成。 await 几乎是 somePromise.then(() => /* next bit of code */) 的语法糖并且是 非阻塞 (如果你 await 一些东西,其他代码仍然可以执行,只是当前功能将暂停)。

虽然您可以在其他语言中使用 while 循环来等待某个任务在另一个线程上完成,但 JavaScript 是单线程的,这样的 while 循环会停止你的初始化代码来自 运行。您需要使用回调或 Promise 才能正确执行此操作。在这两个选项中,我会选择 Promise 方法。这将允许您调用 await init() 并且如果您将承诺缓存在 init() 中,它可能在您需要使用该函数时已经完成并且它会立即 return 结果。这为您省去了必须处理包含所需数据的对象的生命周期管理、编写代码以检查它是否完成、处理初始化中的任何错误以及未来您的头挠头的麻烦。

async function _initDoTheWork() {
  /*
   * Take care of any async initialization here,
   * and return any result as applicable
   */

  const app = firebase.initializeApp();
  return { app }; // just as an example
}

/** 
 * Starts the initialization function, but
 * caches its promise to reuse in future calls
 */
function initDoTheWork() {
  if (!initDoTheWork.promise) {
    initDoTheWork.promise = _initDoTheWork();
  }
  return initDoTheWork.promise;
}

// trigger async work now
// ignore result, but trap errors so you don't get an Unhandled Rejection Exception
initDoTheWork()
  .catch((err) => {
    // you could do nothing here, but I'd log the error somewhere
    console.error("Pre-initialization reported an error", error)
  });

export async function doTheWork() { // the actual function to be exported
  const { app } = await initDoTheWork();

  const db = app.firestore();

  // do stuff with app & db
}

/**
 * Force reinitialization of doTheWork()
 * 
 * Note: Errors must be handled by the caller.
 */
doTheWork.reinitialize = async function reinitialize() {
  initDoTheWork.promise = _initDoTheWork();
  return initDoTheWork.promise;
}