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

问题描述

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

这是 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: '',};

      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 函数在所有回调函数完成执行之前返回列表(空)。

有人可以发现并指出需要更改/添加内容以使函数等待所有回调函数完成。我尝试添加 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: "",};

      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,});

const getList = (bucketName: string,options: GetFilesOptions) => {
  return new Promise((resolve,reject) => {
    // let test: any[] = [];
    let list: any[] = [];
    const callback = (
      _err: any,apiResponse: any
    ) => {
      list = list.concat(apiResponse.prefixes);
      console.log("list : ",list);
      console.log("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,};
    }
  });