尝试在异步云函数(节点v8)内执行fs.writefile()

时间:2019-03-14 11:06:57

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

我目前正在构建云功能,以从电子商务网站中抓取一些数据。我在Node.js v8环境上运行它们,因此我可以使用async/await而无需进行编译。

我需要一种方法来保存网站上的html响应文件,以便我可以对其进行检查并决定如何最好地对其进行抓取。而且我无法使其正常工作。

正如我在许多地方发现的那样,我需要一种使fs.writeFile()函数散布的方法,以便可以await使用它。我尝试过使用util.promisify,并且还在下面构建了自定义函数(两者都产生了相同的结果,这就是我await获得结果时我的云函数崩溃了)

index.js (云功能的主文件-简化版)

const functions = require('firebase-functions');
const request = require('request');
const cheerio = require('cheerio');
const fs = require('fs');

// PROMISIFY WRITEFILE TO SAVE URL RESPONSE
const promisifiedWriteFile = function(text) {
  return new Promise((resolve, reject) => {
    fs.writeFile('./response.html', text, err => {
      if (err) {
        return reject(err);
      }
      return resolve();
    });
  });
};

exports.getUrlProductDetails = functions.https.onCall(
  async (data) => {

    try {
      // SEND REQUEST TO URL PRODUCT PAGE, PARSE WITH CHEERIO
      response = await promisifiedRequest(productURL);
      $ = cheerio.load(response.body);

      // TRYING TO SAVE FILE
      await promisifiedWriteFile('12345'); // <----- THIS IS CRASHING
    } // TRY BLOCK - OUTER - END

    catch (err) {
      console.log(err);
      throw new functions.https.HttpsError('unknown', 'Some internal error', err);
    }

  console.log('End of async function...');

  return {
    productDetails: productDetails,
    body: response.body // My client code is getting the body response just fine
  };

注1::这是代码的简化版本,但是使函数崩溃的单行是:await promisifiedWriteFile('12345');,当我注释掉它时,其他一切都很好。

注意2:,即使此时函数崩溃,文件response.html仍被创建(内容为空)。

注意3::我应该尝试写response.body'12345'仅用于测试。但这两种方式都会崩溃。

我在做什么错了?

编辑

// THIS IS WHAT LOGS OUT OF MY FUNCTION
info: User function triggered, starting execution
info: Execution took 2034 ms, finished with status: 'crash'

这是我的客户端得到的:错误消息只是internal,因为云函数避免了将内部错误详细信息传递给客户端。

enter image description here

注意4::我尚未部署该功能。这一切都取决于地方发展。

2 个答案:

答案 0 :(得分:2)

我相信您不允许在Firebase函数上写入文件系统。尝试写入/tmp,请参阅changelog

但是我认为您不应该writing response.html,而应该在Firebase函数返回的响应中设置文本和状态代码。

答案 1 :(得分:0)

我已经做到了。

根据this Firebase youtube videoos.tmpdir()仅是您的函数代码可写的一个目录。

以下内容也是如此,现在它可以工作了:

index.js

const fs = require('fs');
const os = require('os');
const path = require('path');
const tmpdir = os.tmpdir();
const filePath = path.join(tmpdir,'response.html');

// PROMISIFY WRITEFILE TO SAVE URL RESPONSE
const promisifiedWriteFile = function(text) {
  return new Promise((resolve, reject) => {
    fs.writeFile(filePath, text, err => {
      if (err) {
        return reject(err);
      }
      return resolve();
    });
  });
};

在我正在调用的函数中:

await promisifiedWriteFile(response.body);

也在此链接上找到了一些相关文档:

https://cloud.google.com/functions/docs/concepts/exec