问题描述
我正在使用 Google Storage NodeJS 客户端库来列出 GCS 存储桶路径。
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,};
}
});