Google 翻译 API 和 Firebase Firestore 正在自相残杀

Google Translate API and Firebase Firestore are killing each other

我们正在尝试编写一个 Google Cloud Function,它从 Google Translate API 获取翻译,然后将结果写入我们的 Firebase Firestore 数据库。每个单独工作,但在一起没有任何工作。也就是说,我们可以从 Google Translate 得到一个翻译。我们可以将数据写入 Firestore。但是,如果我们尝试同时执行这两项操作,我们就不会从 Google Translate 获得翻译结果,也不会向 Firebase 写入任何内容。我们没有收到任何错误消息。我们已经用 async await 和 promises 尝试了代码。这是带有承诺的代码:

    exports.Google_EStranslateEN = functions.firestore.document('Users/{userID}/Spanish/Translation_Request').onUpdate((change, context) => {
      if (change.after.data().word != undefined) {
        const {Translate} = require('@google-cloud/translate');
        const projectId = 'myProject-cd99d';
        const translate = new Translate({
          projectId: projectId,
        });

        // The text to translate
        const text = change.after.data().word;
        // The target language
        const target = 'en';

        let translationArray = []; // clear translation array

        translate.translate(text, target)
        .then(results => {
          translation = results[0];
          translationArray.push(translation);

          try {
            // write translation to dictionary
admin.firestore().collection('Dictionaries').doc('Spanish').collection('Words').doc(text).collection('Translations').doc('English').set({
              'translationArray': translationArray,
              'language': 'en',
              'longLanguage': 'English'
            })
            .then(function() {
              console.log("Translation written");
            })
            .catch(function(error) {
              console.error(error);
            });
          } catch (error) {
            console.error(error);
          }
        })
        .catch(error => {
          console.error('ERROR:', error);
        });
      }
    });

这是与 async await 相同的代码:

exports.Google_EStranslateEN = functions.firestore.document('Users/{userID}/Spanish/Translation_Request').onUpdate((change, context) => { // triggers when browser writes a request word to the database
  if (change.after.data().word != undefined) {

async function getTranslation() {
  try {

    let translationArray = []; // clear translation array

    const {Translate} = require('@google-cloud/translate');
    const projectId = 'myProject-cd99d';

    const translate = new Translate({
      projectId: projectId,
    });

    // The text to translate
    const text = change.after.data().word;

    const options = {
      to: 'en',
      from: 'es',
      format: 'text'
    }

    let [translations] = await translate.translate(text, options);
    translations = Array.isArray(translations) ? translations : [translations]; // If translations is an array, leave it alone; if not, put it in an array
    translationArray.push(translations[0]);

    await admin.firestore().collection('Dictionaries').doc('Spanish').collection('Words').doc(text).collection('Translations').doc('English').set({
      'translationArray': translationArray,
      'language': 'en',
      'longLanguage': 'English'
    })
    .then(function() {
      console.log("Translation written");
    })
    .catch(function(error) {
      console.error(error);
    });
    // };
  } catch (error) {
    console.error(error);
  }
} // close getTranslation
getTranslation();   
}
});

您没有return承诺在所有异步工作完成后就解决了。如果您不这样做,Cloud Functions 会假定您的所有工作都已完成,并将限制所有资源,并且任何待处理的工作都将被关闭。

returntranslate.translate().then().catch() 做出的承诺被忽略了。您对 admin.firestore()...set() 的嵌套调用也有类似的问题。仅对每个承诺调用 then()catch() 是不够的,因为 then()catch() 都是 return 又一个承诺。

您还不必要地将 try/catch 与 promise 上的 catch() 混合使用。您不需要两种错误处理策略,只需要其中一种即可。

当您在第二个示例中使用 await 时,您强制 JavaScript 暂停,直到由 set() 编辑的承诺 return 表示的异步工作完成。这允许您的函数仅在所有工作完成后才 return,这就是它正常工作的原因。

观看我的 video series 关于 promises 的使用和 async/await 在 Cloud Functions 中的使用可能会对您有所帮助。正确处理 promises 对于创建正确工作的函数至关重要。