Firebase Cloud Functions中Promise无法解析问题求助
解决Firebase Cloud Functions中Firestore调用卡住超时的问题
我帮你排查了代码里的几个关键问题,这些应该是导致函数卡住超时的核心原因:
1. 重复初始化Firebase Admin是致命错误
你现在在processFile函数内部每次触发都调用admin.initializeApp(),这是严重错误。云函数的实例会被复用,重复初始化Admin会抛出隐藏异常,进而导致后续的Firestore调用卡住或无响应。
修复方案:把Admin初始化移到全局作用域,只执行一次:
import * as functions from 'firebase-functions'; import * as admin from 'firebase-admin'; import * as path from 'path'; import * as WordExtractor from 'word-extractor'; import * as textract from 'textract'; import suffixArray from './suffixArray'; // 全局初始化Admin,仅在实例启动时执行一次 const serviceAccount = require(__dirname + '/../config/serviceAccount.json'); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: 'https://fyp-alex.firebaseio.com', }); // 后续processFile函数内不要再重复初始化admin export const processFile = functions.storage.object().onFinalize(async file => { const firestore = admin.firestore(); // ... 原函数剩余代码保持不变 });
2. getText函数中TXT文件处理未Promise化
你的getText函数处理txt文件时用了textract.fromFileWithPath的回调版本,但没有用Promise包裹,这会导致函数直接返回空字符串(回调还没执行完就提前return了),后续文本处理逻辑异常可能间接影响Firestore调用。
修复方案:将txt处理改为Promise版本:
async function getText(_path: string, fileExt: string) { let text: string = ''; switch (fileExt) { case 'docx': case 'doc': const extractor = new WordExtractor(); const extracted = await extractor.extract(_path); text = extracted.getBody(); break; case 'pdf': // 建议补充PDF文本提取逻辑,当前为空会导致返回空文本 break; case 'txt': // 用Promise包裹回调,确保等待文本提取完成 text = await new Promise((resolve, reject) => { textract.fromFileWithPath(_path, function(extractedError: any, string: string) { if (extractedError) { console.error(extractedError); reject(extractedError); } else { resolve(string || ''); } }); }); break; default: console.log('Unsupported File Type'); } return text; }
3. search函数存在死循环隐患
你的二分查找逻辑有明显错误:
mid计算应为Math.floor((start + end) / 2),而非(end - 1) / 2,会导致非整数索引访问- 循环中
start和end的更新逻辑会触发死循环(比如start=mid时,若mid与start相等,循环永远无法终止)
如果后续执行到该函数,也会导致超时,建议修复:
function search(text: string, searchTerm: string, suffix_array: number[]) { console.log(`Beginning search for: ${searchTerm}`); let start = 0; let end = suffix_array.length - 1; const matchedIndexes: Array<number> = []; // 先定位第一个匹配的位置 let firstMatch = -1; while (start <= end) { const mid = Math.floor((start + end) / 2); const index = suffix_array[mid]; const finalIndex = index + searchTerm.length; if (finalIndex > text.length) { end = mid - 1; continue; } const substring = text.substring(index, finalIndex); const match = searchTerm.localeCompare(substring); if (match === 0) { firstMatch = mid; end = mid - 1; // 继续向前寻找更早的匹配 } else if (match < 0) { end = mid - 1; } else { start = mid + 1; } } // 从第一个匹配位置向后遍历所有匹配项 if (firstMatch !== -1) { for (let i = firstMatch; i < suffix_array.length; i++) { const index = suffix_array[i]; const finalIndex = index + searchTerm.length; if (finalIndex > text.length) break; const substring = text.substring(index, finalIndex); if (searchTerm.localeCompare(substring) === 0) { console.log(`Match Found at Index: ${index}`); matchedIndexes.push(index); } else { break; // 后缀数组有序,后续不会再出现匹配 } } } if (matchedIndexes.length === 0) { console.log(`No matches found for search term: ${searchTerm}`); } return matchedIndexes; }
4. 其他细节修复
allContexts.concat(contexts)不会修改原数组,应改为allContexts.push(...contexts),否则allContexts永远为空,后续无数据写入Firestore- 若处理大文件,建议在Firebase控制台调整函数超时时间(默认60秒)
按照上述步骤修复后,应该能解决Firestore调用卡住的问题。
内容的提问来源于stack exchange,提问作者A. Hewitson
相关产品推荐
相关产品推荐

