在Firebase Cloud Functions中包含异步功能(附加错误“解析错误:意外的令牌功能”)

Ada*_*itz 5 javascript node.js firebase google-cloud-functions firebase-cli

问题

如何将async辅助方法添加到Cloud Functions的 index.js文件中?转换为Promiseasync需要使用一个函数,如本StackOverflow文章中所述:fs.writeFile包含在promise,异步同步中。但是,lint不赞成在功能之外向index.js文件添加其他方法。awaitfs.writefileexports

错误

84行是辅助功能async function writeFile

用户/adamhurwitz/coinverse/coinverse-cloud-functions/functions/index.js 84:7错误解析错误:意外的令牌功能

?1个问题(1个错误,0个警告)

npm ERR!代码ELIFECYCLE

npm ERR!errno 1

npm ERR!功能@棉绒:eslint .

npm ERR!退出状态1

npm ERR!

npm ERR!在functions @ lint脚本上失败。

npm ERR!npm可能不是问题。上面可能还有其他日志记录输出。

npm ERR!可以在以下位置找到此运行的完整日志:

npm ERR!/用户/adamhurwitz/.npm/_logs/2018-12-12T01_47_50_684Z-debug.log

错误:函数预部署错误:命令以非零退出代码终止

设定

index.js

const path = require('path');
const os = require('os');
const fs = require('fs');
const fsPromises = require('fs').promises;
const util = require('util');
const admin = require('firebase-admin');
const functions = require('firebase-functions');
const {Storage} = require('@google-cloud/storage');
const textToSpeech = require('@google-cloud/text-to-speech');

const storage = new Storage({
  projectId: 'project-id',
});
const client = new textToSpeech.TextToSpeechClient();

admin.initializeApp();

exports.getAudiocast = functions.https.onCall((data, context) => {
  const bucket = storage.bucket('gs://[bucket-name].appspot.com');
  var fileName;
  var tempFile;
  var filePath;

  return client.synthesizeSpeech({
    input: {text: data.text },
    voice: {languageCode: 'en-US', ssmlGender: 'NEUTRAL'},
    audioConfig: {audioEncoding: 'MP3'},
  })
  .then(responses => {
    var response = responses[0]; 
    fileName = data.id + '.mp3'
    tempFile = path.join(os.tmpdir(), fileName);  
    return writeFile(tempFile, response.audioContent)
  })
  .catch(err => {
    console.error("Synthesize Speech Error: " + err);
  })
  .then(() => {
     filePath = "filePath/" + fileName;
     return bucket.upload(tempFile, { destination: filePath })
  })
  .catch(err => {
     console.error("Write Temporary Audio File Error: " + err);
  })
  .then(() => {
   return { filePath: filePath }
  })
  .catch(err => {
     console.error('Upload Audio to GCS ERROR: ' + err);
  });
});
Run Code Online (Sandbox Code Playgroud)

辅助方法:

async function writeFile(tempFile, audioContent) {
    await fs.writeFile(tempFile, audioContent, 'binary');
}
Run Code Online (Sandbox Code Playgroud)

尝试的解决方案

按照“ 为Firebase异步等待样式”中的Cloud Functions中的建议启用Node.js 8

  1. 设置Node.js版本 "engines": {"node": "8"}

  2. return await fs.writeFile(tempFile, audioContent, 'binary');

棉绒不喜欢这种解决方案。

Flo*_*n K 63

我尝试了上述所有对我不起作用的解决方案。这是由于我的 package.json 中的语法错误:

"scripts": {
    "lint": "eslint ."
  },
Run Code Online (Sandbox Code Playgroud)

变成 :

"scripts": {
    "lint": "eslint"
  },
Run Code Online (Sandbox Code Playgroud)

就像评论中的 Burak 所说的那样,当我们创建 firebase 函数时,默认情况下会放置这个点

  • 截至 2021 年 2 月,这仍然是一个问题。将 lint 更改为“eslint”可以解决此问题。 (11认同)
  • 在目录中创建 Firebase 函数后,默认情况下会放置此点。然而,奇怪的是,如果你删除它,问题就解决了。 (5认同)
  • 我不确定这是否能解决问题。根据我的经验,它使 eslint 针对错误的目标目录工作。尝试使用不好的缩进,它就不会再被标记 (2认同)
  • 小心这一点。也许我错过了一些东西,但对我来说,这个“修复”完全关闭了 lint 警告。 (2认同)

小智 15

ISSUE ES7 你必须将其更改为ES8

  • 2016 年发布的 ES7 没有 async、await 和箭头函数
  • 2017 年发布的 ES8 有 async、await 和 arrow 函数

你必须检查你的 .eslintrc 是否至少有 es8 或 2017,这是相同的。

如果文件是 .eslintrc.json

“ecmaVersion”:2017 或“ecmaVersion”:8

如果文件是 .eslintrc.js

env:{ es8:true, 节点:true }

对于某些人来说是这样的

就我而言,它通过更改 package.json 解决了

“脚本”:{“lint”:“eslint”。},

变成 :

“脚本”:{“lint”:“eslint”},

正如乔纳森所说,但我想知道为什么?

并意识到我有两个文件的名称

  • .eslintrc.js
  • .eslintrc.json

这是 eslintrc.json

这是 eslintrc.json

如您所见,两个同名文件中有不同版本的 ecmaScript,

  • "ecmaVersion": 2017 // 等于文件 .eslintrc.json 中的 es8
  • es6: true, // 于 2015 年 6 月在文件:.eslintrc.js 中发布

因此,当我们运行:npm run lint时,它会使用 es6:true 运行 .eslintrc.js,因此要解决此冲突,只需删除 .eslintrc.js,因为它有错误的 ecmaScript。


smo*_*mok 14

如果你有.eslint.js- 只需更改es6: truees2017: true.

例如:

  env: {
    es6: true,
    node: true,
  },
Run Code Online (Sandbox Code Playgroud)

变成:

  env: {
    es2017: true,
    node: true,
  },
Run Code Online (Sandbox Code Playgroud)

更多详细信息请参见ESLint 语言选项文档


Dou*_*son 10

您的eslint未配置为了解ECMAScript 2017语法。Fireabse CLI默认创建的.eslint.json配置文件包括以下配置:

"parserOptions": {
  // Required for certain syntax usages
  "ecmaVersion": 6
},
Run Code Online (Sandbox Code Playgroud)

像这样更改它以帮助它了解异步/等待:

  "ecmaVersion": 2017
Run Code Online (Sandbox Code Playgroud)

  • 我在项目中的* eslintrc.json *文件中添加了“ ecmaVersion”:2017“,但是当返回由await生成的promise时,** Lint **仍会引发错误:return await fs。 writeFile(tempFile,response [0] .audioContent,'binary');` (2认同)
  • 确实,最新版本在 env 部分采用“es2017: true”格式 (2认同)

Ada*_*itz 2

Node.js 8 - Promisify

按照Cloud Functions for Firebase Async Await style中的建议启用 Node.js 8

  1. 设置 Node.js 版本 "engines": {"node": "8"}
  2. 使用promisify

    const writeFile = util.promisify(fs.writeFile);

    return writeFile(tempFile, response.audioContent, 'binary')

Node.js 8 之前的版本 - 手动转换

这是一种将回调转换为 Promise 的旧方法,如有关 Google Text To Speech ( TTS ) 的更具体问题的答案所述。

const writeFilePromise = (file, data, option) => {
   return new Promise((resolve, reject) => {
       fs.writeFile(file, data, option, error => {
          if (error) reject(error);
          resolve("File created! Time for the next step!");
       });
   });
};

return writeFilePromise(tempFile, response.audioContent, 'binary');
Run Code Online (Sandbox Code Playgroud)