在 Firebase 云函数中包含异步函数(eslint“解析错误:意外的令牌函数”)

Posted

技术标签:

【中文标题】在 Firebase 云函数中包含异步函数(eslint“解析错误:意外的令牌函数”)【英文标题】:Including Async Function Within Firebase Cloud Functions (eslint "Parsing error: Unexpected token function") 【发布时间】:2019-05-13 02:02:34 【问题描述】:

问题

如何将async 辅助方法添加到Cloud Functions' index.js 文件中?在将 fs.writefile 转换为 Promise 时,需要 async 函数才能使用 await,如 *** 帖子中所述:fs.writeFile in a promise, asynchronous-synchronous stuff。但是,lint 不赞成在 index.js 文件中添加 exports 函数之外的其他方法。

错误

84行引用了辅助函数async function writeFile

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

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

npm 错误!代码生命周期

npm 错误!错误号 1

npm 错误!函数@ lint:eslint .

npm 错误!退出状态 1

npm 错误!

npm 错误! functions@lint 脚本失败。

npm 错误!这可能不是 npm 的问题。上面可能还有额外的日志输出。

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

npm 错误! /Users/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);
  );
);

辅助方法:

async function writeFile(tempFile, audioContent) 
    await fs.writeFile(tempFile, audioContent, 'binary');

尝试的解决方案

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

    Set Node.js version "engines": "node": "8"

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

Lint 不喜欢这种解决方案。

【问题讨论】:

【参考方案1】:

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

"scripts": 
    "lint": "eslint ."
  ,

改为:

"scripts": 
    "lint": "eslint"
  ,

就像在 cmets 中说的 Burak 一样,这个点在我们创建 firebase 函数时默认放置

【讨论】:

我不确定这是否能解决问题。根据我的经验,它使 eslint 对错误的目标目录起作用。尝试有不好的缩进,它不会被标记了 对此要小心。也许我错过了一些东西,但对我来说,这个“修复”完全关闭了 lint 警告。 这不是一个修复它不会让 eslint “工作”——它让 eslint 实际上不会扫描你的代码。如果你打算这样做,你也可以删除整个 lint 脚本。【参考方案2】:

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

"parserOptions": 
  // Required for certain syntax usages
  "ecmaVersion": 6
,

像这样改变它以帮助它理解 async/await:

  "ecmaVersion": 2017

【讨论】:

我已将"ecmaVersion": 2017 添加到项目的 eslintrc.json 文件中,但是 Lint 在返回承诺时仍然抛出错误从await生成:return await fs.writeFile(tempFile, responses[0].audioContent, 'binary'); 这听起来像是一个不同的问题。 唯一的区别是将promisify替换为await。否则,writeFile 方法在使用 promisify 时会按预期工作,因此我可以继续使用该方法。 没错,最新版本在 env 部分采用es2017: true 格式【参考方案3】:

ISSUE ES7 你必须把它改成 ES8

2016 年发布的 ES7 没有 async、await 和箭头函数 2017 年发布的 ES8 具有异步、等待和箭头功能

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

如果文件是 .eslintrc.json

“ecmaVersion”:2017 要么 “ecmaVersion”:8

如果文件是 .eslintrc.js

环境: es8:真的, 节点:真

对于某些人来说,它是这样工作的

在我的情况下,它通过更改 package.json 解决了

"scripts": "lint": "eslint." ,

改为:

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

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

a 意识到我有两个同名的文件

.eslintrc.js .eslintrc.json

this is eslintrc.json

this is eslintrc.json

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

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

所以当我们运行时: npm run lint 它运行 .eslintrc.js 并带有 es6:true 所以解决这个冲突只是删除.eslintrc.js,因为它有错误的ecmaScript。

【讨论】:

【参考方案4】:

如果您有 .eslint.js - 只需将 es6: true 更改为 es2017: true

例如:

  env: 
    es6: true,
    node: true,
  ,

变成:

  env: 
    es2017: true,
    node: true,
  ,

更多详情请见ESLint language options doc。

【讨论】:

【参考方案5】:

Node.js 8 - 承诺

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

    Set Node.js version "engines": "node": "8"

    使用promisify

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

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

Pre Node.js 8 - 手动转换

这是answer 所概述的将回调转换为承诺的旧方法,涉及有关 Google 文本转语音 (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');

【讨论】:

"engines": "node": "8" 对我来说是关键,非常感谢【参考方案6】:

更改 .eslintrc.json 中的 ecmaVersion

“解析器选项”: // 某些语法用法需要 “ecmaVersion”:8

【讨论】:

【参考方案7】:

.eslint.json

“解析器选项”: // 某些语法用法需要 “ecmaVersion”:6 , 像这样改变它以帮助它理解 async/await:

“ecmaVersion”:2017

package.json “脚本”: “lint”:“eslint”。 , 改为:

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

引用韦伯上尉和道格·史蒂文森

【讨论】:

请阅读formatting help page 以改进您的答案格式,并查看How do I write a good answer? 以改进您的答案。

以上是关于在 Firebase 云函数中包含异步函数(eslint“解析错误:意外的令牌函数”)的主要内容,如果未能解决你的问题,请参考以下文章

在 FCM(Firebase 云消息传递)中,在通知中包含令牌是不是安全?

Firebase 异步等待风格的云函数

在 Swift 的异步调用中包含返回处理程序

Angular 和 Firebase 云函数返回 null

JavaScript的异步编程

ES2017异步函数现已正式可用