Firebase 函数 Returns 在所有回调函数完成执行之前

Firebase Function Returns Before All Callback functions complete execution

我正在使用 Google Storage NodeJS 客户端库来列出 GCS Bucket 路径。

这是 Firebase 函数的代码:

import * as functions from 'firebase-functions';
import { Storage } from '@google-cloud/storage';
import { globVars } from '../admin/admin';

const projectId = process.env.GCLOUD_PROJECT;
// shared global variables setup
const { keyFilename } = globVars;
// Storage set up
const storage = new Storage({
  projectId,
  keyFilename,
});

export const gcsListPath = functions
  .region('europe-west2')
  .runWith({ timeoutSeconds: 540, memory: '256MB' })
  .https.onCall(async (data, context) => {
    if (context.auth?.token.email_verified) {
      const { bucketName, prefix, pathList = false, fileList = false } = data;
      let list;
      const options = {
        autoPaginate: false,
        delimiter: '',
        prefix,
      };

      if (pathList) {
        options.delimiter = '/';

        let test: any[] = [];
        const callback =  (_err: any, _files: any, nextQuery: any, apiResponse: any) => {
          test = test.concat(apiResponse.prefixes);
          console.log('test : ', test);
          console.log('nextQuery : ', nextQuery);
          if (nextQuery) {
            storage.bucket(bucketName).getFiles(nextQuery, callback);
          } else {
            // prefixes = The finished array of prefixes.
            list = test;
          }
        }
       storage.bucket(bucketName).getFiles(options, callback);
      }

      if (fileList) {
        const [files] = await storage
          .bucket(bucketName)
          .getFiles(options);
        list = files.map((file) => file.name);
        
      }

      return { list }; //returning null as it exec before callback fns finish

    } else {
      return {
        error: { message: 'Bad Request', status: 'INVALID_ARGUMENT' },
      };
    }
  });

我的问题是我的 Firebase 函数 returns 在所有回调函数完成执行之前的列表(空)。

有人可以发现并指出需要什么 changed/added 才能使函数等待所有回调函数完成。我尝试添加 async/await 但似乎无法正确添加。

您的错误原因是您使用了callback。代码中没有等待它。我建议将 callback 代码转换为承诺。像这样。

import * as functions from "firebase-functions";
import { Storage } from "@google-cloud/storage";
import { globVars } from "../admin/admin";

const projectId = process.env.GCLOUD_PROJECT;
// shared global variables setup
const { keyFilename } = globVars;
// Storage set up
const storage = new Storage({
  projectId,
  keyFilename,
});

const getList = (bucketName, options) => {
  return new Promise((resolve, reject) => {
    let list;
    let test: any[] = [];
    const callback = (
      _err: any,
      _files: any,
      nextQuery: any,
      apiResponse: any
    ) => {
      test = test.concat(apiResponse.prefixes);
      console.log("test : ", test);
      console.log("nextQuery : ", nextQuery);
      if (nextQuery) {
        storage.bucket(bucketName).getFiles(nextQuery, callback);
      } else {
        // prefixes = The finished array of prefixes.
        list = test;
      }

      resolve(list);
    };

    try {
      storage.bucket(bucketName).getFiles(options, callback);
    } catch (error) {
      reject(eror);
    }
  });
};

export const gcsListPath = functions
  .region("europe-west2")
  .runWith({ timeoutSeconds: 540, memory: "256MB" })
  .https.onCall(async (data, context) => {
    if (context.auth?.token.email_verified) {
      const { bucketName, prefix, pathList = false, fileList = false } = data;
      let list;
      const options = {
        autoPaginate: false,
        delimiter: "",
        prefix,
      };

      if (pathList) {
        options.delimiter = "/";

        list = await getList(bucketName, options);
      }

      if (fileList) {
        const [files] = await storage.bucket(bucketName).getFiles(options);
        list = files.map((file) => file.name);
      }

      return { list }; //returning null as it exec before callback fns finish
    } else {
      return {
        error: { message: "Bad Request", status: "INVALID_ARGUMENT" },
      };
    }
  });

我不确定带有 fileList 的部分是否会按预期工作。看起来 API 不支持等待,只支持回调。

import * as functions from "firebase-functions";
import { GetFilesOptions, Storage } from "@google-cloud/storage";
import { globVars } from "../admin/admin";

const projectId = process.env.GCLOUD_PROJECT;
// shared global variables setup
const { keyFilename } = globVars;
// Storage set up
const storage = new Storage({
  projectId,
  keyFilename,
});

const getList = (bucketName: string, options: GetFilesOptions) => {
  return new Promise((resolve, reject) => {
    // let test: any[] = [];
    let list: any[] = [];
    const callback = (
      _err: any,
      _files: any,
      nextQuery: any,
      apiResponse: any
    ) => {
      list = list.concat(apiResponse.prefixes);
      console.log("list : ", list);
      console.log("nextQuery : ", nextQuery);
      if (nextQuery) {
        storage.bucket(bucketName).getFiles(nextQuery, callback);
      } else {
        // prefixes = The finished array of prefixes.
        resolve(list);
      }

    };

    try {
      storage.bucket(bucketName).getFiles(options, callback);
    } catch (error) {
      reject(error);
    }
  });
};

export const gcsListPath = functions
  .region("europe-west2")
  .runWith({ timeoutSeconds: 540, memory: "256MB" })
  .https.onCall(async (data, context) => {
    if (context.auth?.token.email_verified) {
      const { bucketName, prefix, pathList = false, fileList = false } = data;
      let list;
      const options = {
        autoPaginate: false,
        delimiter: "",
        prefix,
      };

      if (pathList) {
        options.delimiter = "/";

        list = await getList(bucketName, options);
      }

      if (fileList) {
        const [files] = await storage.bucket(bucketName).getFiles(options);
        list = files.map((file) => file.name);
      }

      return { list }; //returning null as it exec before callback fns finish
    } else {
      return {
        error: { message: "Bad Request", status: "INVALID_ARGUMENT" },
      };
    }
  });