You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:17:10