【问题标题】:Can't read hosting files in a cloud Function无法读取云中的托管文件功能
【发布时间】:2018-07-02 16:14:39
【问题描述】:

我的 Firebase 功能无法正常工作。这是日志:

11:01:03.932 AM warning getWatsonToken Error: ENOENT: no such file or directory, open '../public/javascript/services/watsonTokenValue.js'
    at Error (native)

11:01:03.831 AM warning getWatsonToken Uncaught exception

11:01:03.233 AM info    getWatsonToken 5YGY3R%2FBP0zelDOaob9PnxMWDj...

11:01:00.139 AM outlined_flag getWatsonToken Function execution took 804 ms, finished with status: 'ok'

11:00:59.834 AM info    getWatsonToken Executing function!

11:00:59.335 AM outlined_flag getWatsonToken Function execution started

我不知道“未捕获的异常”指的是什么。

“ENOENT:没有这样的文件或目录”错误可能是节点路径错误。这是我的目录结构:

── functions
    ├── index.js // this is my function
── public
    ├── javascript
    │   ├── services
    │   │   ├── watsonTokenValue.js // this is the file I want to write to

这是显然导致错误的行:

fs.writeFile('../public/javascript/services/watsonTokenValue.js', tokenService, (err) => {

该行使用 Node 写入文件。路径有问题吗?

这是完整的功能:

// Node modules
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const request = require('request'); // node module to send HTTP requests
const fs = require('fs');

admin.initializeApp(functions.config().firebase);

exports.getWatsonToken = functions.database.ref('userLoginEvent').onUpdate(event => { // authentication trigger when user logs in
  console.log("Executing function!");
  var username = '56ae6a1e7854',
  password = 'swordfish',
  url = 'https://' + username + ':' + password + '@stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api';

  request({url: url}, function (error, response, body) {
    console.log(body);
    var tokenService = "app.value('watsonToken','" + body + "');";

    fs.writeFile('../public/javascript/services/watsonTokenValue.js', tokenService, (err) => {
      if (err) throw err;
      console.log('The file has been saved!');
    }); // close fs.writeFile

  }); // close request
return 0; // prevents an error message "Function returned undefined, expected Promise or value"
}); // close getWatsonToken

前四行加载 Node 模块。该函数称为“getWatsonToken”。它在用户登录时触发,或者,具体而言,当登录过程中的一行代码将用户的 Auth ID 写入 Firebase 实时数据库中的某个位置时触发,然后 onUpdate 触发该函数。接下来,为 HTTP 请求定义参数,然后将 HTTP 请求发送到 IBM Watson。 IBM 为其语音到文本服务返回一个令牌作为 HTTP 响应的正文。 (console.log 显示了令牌,它正在工作。)然后一些 Angular JavaScript 被包裹在令牌周围。最后,将文件写入目录中的某个位置。最后一步似乎是错误所在。

这是我的目录结构的另一个视图:

感谢您的帮助!

【问题讨论】:

  • Do not post images of code or errors! 图片和屏幕截图可以很好地添加到帖子中,但请确保帖子在没有它们的情况下仍然清晰有用。如果您发布代码或错误消息的图像,请确保您还复制并粘贴或直接在帖子中输入实际代码/消息。
  • 谢谢,我刚刚编辑了错误文本。

标签: javascript node.js firebase google-cloud-functions firebase-hosting


【解决方案1】:

您不能使用云函数来读取和写入由 Firebase 托管提供的文件,即使在同一个项目中也是如此。

当您使用 Firebase CLI 进行部署时,每个产品都是单独部署的。因此,public 文件夹中用于 Firebase 托管的所有静态内容都会发送到一个地方,而您的所有 Cloud Functions 代码都会发送到另一个地方。之后,他们就没有共同点了。

可以在部署后读取functions 文件夹下的文件。但显然,这些与部署后的托管无关。

我强烈建议不要尝试在云函数中写入文件,尤其是对于您的用例。通过将持久性数据写入实时数据库、Firestore 甚至云存储来更好地为您提供更好的服务。 Cloud Functions 中的磁盘文件不是持久的,您可能有多个服务器实例运行彼此不知道的函数。

【讨论】:

  • 您是说我的函数应该将令牌保存在实时数据库中,然后我的控制器应该监视该位置的更改,然后下载令牌并编写 Angular 文件?我试试看,谢谢!
  • @DougStevenson 如何读取函数文件夹中的文件。我试过使用 fs 但它不起作用?
  • @Po10cio 发布一个新问题,解释您在做什么以及哪些方面没有按您预期的方式工作。
  • @DougStevenson 我已经做到了,这是链接:stackoverflow.com/questions/54356603/…
【解决方案2】:

谢谢,道格!这是我正在使用的 Firebase 功能:

// Node modules
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const request = require('request'); // node module to send HTTP requests
const fs = require('fs');

admin.initializeApp(functions.config().firebase);
exports.getWatsonToken = functions.database.ref('userLoginEvent').onUpdate(event => { // authentication trigger when user logs in
  var username = '56ae6a1e7854',
  password = 'swordfish',
  url = 'https://' + username + ':' + password + '@stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api';
  request({url: url}, function (error, response, body) {
    admin.database().ref('IBMWatsonToken').set({'token': body})
    .then(function()  {
      console.log("Token saved!");
    }); // close promise
  }); // close request
return 0; // prevents an error message "Function returned undefined, expected Promise or value"
}); // close getWatsonToken

这会将令牌写入我的 Firebase 实时数据库。我的控制器代码是:

firebase.database().ref('IBMWatsonToken').on('value', function(snapshot) {
    snapshot.forEach(function(childSnapshot) {
    $scope.watsonToken = childSnapshot.val();
    });
  });

此代码引用 Firebase 实时数据库中的位置,然后 on 侦听值的变化,然后 forEach 读取值并将值放在 $scope 上以供控制器函数使用。

我将通过删除函数中的 promise 和 console.log 使其更快。

【讨论】:

    猜你喜欢
    • 2020-06-13
    • 1970-01-01
    • 2018-08-27
    • 2018-08-07
    • 2011-02-28
    • 1970-01-01
    • 2018-12-05
    • 2020-05-18
    • 1970-01-01
    相关资源
    最近更新 更多