Firebase Cloud功能:承诺无法解决

时间:2019-02-27 13:39:09

标签: javascript firebase promise google-cloud-firestore google-cloud-functions

我的云函数中的某个特定调用存在一些问题,但似乎无法正确解决。

这是不想解析的代码:

console.log('Getting Search Patterns');
let searchPatterns: FirebaseFirestore.QuerySnapshot;
  try {
    searchPatterns = await admin
      .firestore()
      .collection('FYP_LOCATIONS')
      .get();
    } catch (error) {
      console.error(error);
    }
 console.log(`Search Patterns Received: ${searchPatterns}`);

日志: enter image description here

正如您在日志中看到的那样,我的函数将运行直到try块之前的控制台日志,然后停止直到函数超时。我不确定是什么原因导致了此问题。

编辑:通过将云函数中的每个不同部分分离为可以调用的单独函数,我对代码进行了重新格式化;得到的getSearchTerms()函数如下:

async function getSearchTerms(): Promise<FirebaseFirestore.DocumentData[]> {
  try {
    const snapshot = await admin
      .firestore()
      .collection('FYP_LOCATIONS')
      .get();
    console.log('Get Returned');
    return snapshot.docs.map(doc => doc.data());
  } catch (e) {
    console.error(e);
    return [];
  }
}

这仍然在函数执行的同一点停止,完整的功能在这里,它已更新为最新版本:

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';

// 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 serviceAccount = require(__dirname + '/../config/serviceAccount.json');

  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: 'https://fyp-alex.firebaseio.com',
  });

  const firestore = admin.firestore();

  const fileBucket: string = file.bucket;
  const filePath: string = file.name;
  const fileDet: string = path.basename(filePath);
  const fileNameSplit: string[] = fileDet.split('.');
  const fileExt: string = fileNameSplit.pop();
  const fileName: string = fileNameSplit.join('.');
  const bucket = admin.storage().bucket(fileBucket);
  const fileRef = bucket.file(filePath);
  const _path: string = `/tmp/${fileName}.${fileExt}`;
  console.log(`File path ${filePath}`);
  console.log('Getting Download URL');
  try {
    console.log(`Downloading to: ${_path}`);
    await fileRef.download({ destination: _path });
    console.log('File Saved');
    console.log(`Getting Details: ${_path}`);
    const text: string = await getText(_path, fileExt);
    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');
    const searchTerms: FirebaseFirestore.DocumentData[] = await getSearchTerms();
    console.log('Search Patterns Received');
    const promises = [];
    const allContexts: Object[] = [];
    for (const searchDoc of searchTerms) {
      const searchTerm = searchDoc.location_name.toLowerCase();
      console.log(searchTerm);
      const matchedIndexes = search(text, searchTerm, suffix_array);
      const contexts = createContexts(matchedIndexes, searchDoc, text, fileName);
      allContexts.concat(contexts);
    }
    for (const context of allContexts) {
      const p = admin
        .firestore()
        .collection('FYP_CONTEXTS')
        .add(context);
      promises.push(p);
    }
    await Promise.all(promises);
    const data = {
      processed: 1,
    };
    return firestore.doc(`FYP_FILES/${fileName}`).update(data);
  } catch (e) {
    console.error(e);
    const data = {
      processed: 2,
    };
    return firestore.doc(`FYP_FILES/${fileName}`).update(data);
  }
});

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':
      break;
    case 'txt':
      textract.fromFileWithPath(_path, function(extractedError: any, string: string) {
        if (extractedError) {
          console.error(extractedError);
        }
        if (string !== null) {
          text = string;
        }
      });
      break;
    default:
      console.log('Unsupported File Type');
  }
  return text;
}

async function getSearchTerms(): Promise<FirebaseFirestore.DocumentData[]> {
  try {
    const snapshot = await admin
      .firestore()
      .collection('FYP_LOCATIONS')
      .get();
    console.log('Get Returned');
    return snapshot.docs.map(doc => doc.data());
  } catch (e) {
    console.error(e);
    return [];
  }
}

function createContexts(
  matchedIndexes: number[],
  searchDoc: FirebaseFirestore.DocumentData,
  text: string,
  fileName: string
) {
  console.log('Creating Contexts');
  const contexts = [];
  const searchTerm = searchDoc.location_name.toLowerCase();
  for (const index of matchedIndexes) {
    let left = index - 25;
    let right = index + searchTerm.length + 25;
    if (left < 0) {
      left = 0;
    }
    if (right > text.length) {
      right = text.length;
    }
    const context = text.substring(left, right);
    contexts.push({
      lid: searchDoc.lid,
      context_string: context,
      fid: fileName,
    });
  }
  return contexts;
}

function search(text: string, searchTerm: string, suffix_array: number[]) {
  console.log(`Beginning search for: ${searchTerm}`);
  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 + searchTerm.length;
    if (finalIndex <= text.length) {
      const substring: string = text.substring(index, finalIndex);
      const match: number = searchTerm.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: ${searchTerm}`);
  }

  return matchedIndexes;
}

希望完整功能可以提供更多上下文。

我已经看了几次道格的视频,但是我仍然反对,我确实注意到,删除似乎失败的等待(就像一起删除承诺)似乎会导致更早的等待失败。这表明该功能稍后会在功能中出现问题,但是我一生无法找到问题,我会继续尝试,但希望能提供一些有用的上下文。

1 个答案:

答案 0 :(得分:0)

异步操作完成时,您不会让函数知道。 我猜想您想将所有异步操作收集到一个数组中,并等待所有这些异步操作完成后再退出函数。

(上面评论中提到的Doug的youtube视频非常好,并且在解释为什么方面做得更加透彻)

即。

const requests = [];
const things = [1,2,3];
for (let index = 0; index < things.length; index++) {
  const element = things[index];
  const promise = firebase.firestore().push(element);
  requests.push(promise);
}

return Promise.all(requests);