Firebase云功能:承诺未执行

时间:2019-02-20 15:56:07

标签: typescript firebase google-cloud-firestore google-cloud-functions firebase-storage

我在firebase云功能中的promise遇到麻烦。 我想要做的是拿一个文档,从中提取文本并在该文本中搜索一些搜索词。

我遇到的问题是关于诺言。

编辑: 我已经附上了当前正在使用的代码,不再使用子函数来拆分代码,而现在这一切都在一个大块中。

这应该有助于调试。

当试图在第93行检索搜索模式时,当前卡住了。这将在执行此点后停止代码,但是我不知道为什么此Firestore查询无法正常工作。

我添加了@augustzf建议的修复程序。

import functions = require('firebase-functions');
import admin = require('firebase-admin');
import path = require('path');
import suffixArray from './suffixArray';

interface suffix {
  index: number;
  rank: Array<any>;
}

interface Location {
  lid: string;
  location_name: string;
  location_type: string;
  sentimental_value: number;
}

interface Context {
  lid: string;
  context_string: string;
  fid: string;
}

export const processFile = functions.storage.object().onFinalize(async file => {
  const fileBucket = file.bucket;
  const filePath = file.name;

  console.log(`File path ${filePath}`);

  const serviceAccount = require(__dirname + '/../config/serviceAccount.json');

  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: 'someDB'
  });

  const firestore = admin.firestore();
  const settings = { timestampsInSnapshots: true };
  firestore.settings(settings);

  const fileDet = path.basename(filePath);
  const fileNameSplit = fileDet.split('.');
  const fileExt = fileNameSplit.pop();
  const fileName = fileNameSplit.join('.');
  const bucket = admin.storage().bucket(fileBucket);
  const fileRef = bucket.file(filePath);
  const searchTerms = file.metadata.searchTerms.split(', ');
  let _path = '';
  console.log('Getting Download URL');
  try {
    _path = `/tmp/${fileName}.${fileExt}`;
    console.log(`Downloading to: ${_path}`);
    await fileRef.download({ destination: _path });
    console.log('File Saved');
  } catch (e) {
    console.error(e);
  }
  console.log(`Getting Details: ${_path}`);
  let text: string = '';

  switch (fileExt) {
    case 'docx':
    case 'doc':
      const WordExtractor = require('word-extractor');
      const extractor = new WordExtractor();
      const extracted = await extractor.extract(_path);
      text = extracted.getBody();
      break;
    case 'pdf':
      break;
    case 'txt':
      const textract = require('textract');
      textract.fromFileWithPath(_path, function(extractedError, string) {
        if (extractedError) {
          console.error(extractedError);
        }
        if (string !== null) {
          text = string;
        }
      });
      break;
    default:
      console.log('Unsupported File Type');
      return null;
  }
  console.log(`Processing: ${fileName}`);
  console.log('Creating Suffix Array');
  const suffix_array = suffixArray(text);
  console.log(`Suffix Array Created: ${suffix_array}`);
  console.log('Getting Search Patterns');
  let searchPatterns;
  try {
    searchPatterns = await admin
      .firestore()
      .collection('FYP_LOCATIONS')
      .get();
    } catch (error) {
      console.error(error);
    }
    console.log(`Search Patterns Received: ${searchPatterns}`);
    const contexts: Array<Context> = [];
    console.log('Creating Contexts');
    for (const searchPattern of searchPatterns.docs) {
      const patternDoc = searchPattern.data();
      const pattern: string = patternDoc.location_name.toLowerCase();
      console.log(pattern);
      console.log(`Beginning search for: ${pattern}`);
      let start = 0;
      let end = suffix_array.length;
      const matchedIndexes: Array<number> = [];

      while (start < end) {
        const mid: number = (end - 1) / 2;
        const index: number = suffix_array[mid];
        const finalIndex: number = index + pattern.length;
        if (finalIndex <= text.length) {
          const substring: string = text.substring(index, finalIndex);
          const match: number = pattern.localeCompare(substring);

          if (match === 0) {
            console.log(`Match Found at Index: ${index}`);
            matchedIndexes.push(index);
          } else if (match < 0) {
            end = mid;
          } else if (match > 0) {
            start = mid;
          }
          console.log(matchedIndexes);
        }
      }

      if (matchedIndexes.length === 0) {
        console.log(`No matches found for search term: ${pattern}`);
      }
      for (const index of matchedIndexes) {
        let left = index - 25;
        let right = index + patternDoc.location_name.length + 25;
        if (left < 0) {
          left = 0;
        }
        if (right > text.length) {
          right = text.length;
        }
        const context = text.substring(left, right);
        contexts.push({
          lid: patternDoc.lid,
          context_string: context,
          fid: fileName
        });
      }
    }
    for (const context of contexts) {
      admin
        .firestore()
        .collection('FYP_CONTEXTS')
        .add(context)
        .then(contextDoc => {
          console.log(`Context Added: ${contextDoc}`);
        })
        .catch(error => {
          console.error(error);
        });
    }
  const data = {
    processed: 1
  };
  return admin
    .firestore()
    .doc('FYP_FILES/' + fileName)
    .update(data);
});

我已经尝试了多种方法来尝试解决此问题,但是没有提出任何建议,我感觉这与代码中的其他现有Promise有关,但我不确定。

您可以提供的任何帮助将不胜感激。 :)

谢谢, 亚历克斯

1 个答案:

答案 0 :(得分:0)

通常,应避免将forEach与异步方法一起使用。这是因为forEach将在不保留(并因此而等待)返回的诺言的情况下启动每个异步调用。

在您的情况下,这似乎是您的方法存在的问题:

contexts.forEach(async (context: Context) => {
    try {
    const contextDoc = await admin
        .firestore()
        .collection('FYP_CONTEXTS')
        .add(context);
    console.log(`Context Added: ${contextDoc}`);
    } catch (error) {
    console.error(error);
    }
});

这样会更好:

for (const context of contexts) {
    try {
        const contextDoc = await admin
            .firestore()
            .collection('FYP_CONTEXTS')
            .add(context);
        console.log(`Context Added: ${contextDoc}`);
    } catch (error) {
        console.error(error);
    }
}