Je suis en train de créer une fonction cloud pour extraire certaines données des sites Web de commerce électronique. Je les exécute sur l'environnement Node.js v8, je peux donc utiliser async/await sans transpiler.

J'ai besoin d'un moyen d'enregistrer un fichier avec la réponse html du site Web afin que je puisse l'inspecter et décider de la meilleure façon de le gratter. Et je n'ai pas réussi à le faire fonctionner.

Comme j'ai trouvé des recherches dans de nombreux endroits, j'ai besoin d'un moyen de promettre la fonction fs.writeFile() afin que je puisse await pour cela. J'ai essayé avec util.promisify et j'ai également créé la fonction personnalisée ci-dessous (les deux produisent le même résultat, c'est-à-dire que ma fonction cloud se bloque lorsque je await pour le résultat) :

index.js (fichier principal pour les fonctions cloud - version simplifiée)

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
  };

Note1 : Il s'agit d'une version simplifiée du code, mais la seule ligne qui fait planter la fonction est : await promisifiedWriteFile('12345'); et lorsque je la commente, tout le reste fonctionne très bien.

Remarque2 : Le fichier response.html est créé (avec un contenu vide), même avec le plantage de la fonction à ce stade.

Remarque3 : je devrais essayer d'écrire le response.body. Le '12345' est juste pour tester. Mais ça plante de toute façon.

Qu'est-ce que je fais mal?

MODIFIER

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

Et voici ci-dessous ce que mon client obtient : le message d'erreur est simplement internal, car les fonctions cloud évitent de transmettre les détails de l'erreur interne au client.

enter image description here

Remarque4 : Je n'ai pas encore déployé la fonction. Tout est dans le développement local.

2
cbdeveloper 14 mars 2019 à 14:06

2 réponses

Meilleure réponse

J'ai réussi à le faire.

D'après cette vidéo youtube Firebase, la os.tmpdir() une seule répertoire accessible en écriture par le code de votre fonction.

Alors fait ce qui suit et maintenant cela fonctionne:

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();
    });
  });
};

Et depuis l'intérieur de la fonction que j'appelle :

await promisifiedWriteFile(response.body);

J'ai trouvé une documentation connexe également sur ce lien :

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

2
cbdeveloper 13 juil. 2020 à 08:10

Je pense que vous n'êtes pas autorisé à écrire dans le système de fichiers sur les fonctions Firebase. Essayez d'écrire à /tmp, consultez l'article Est-ce que Cloud Functions pour Firebase est compatible opération de fichier ?.

Mais je pense que vous ne devriez pas être writing response.html, à la place, vous devez définir le texte et le code d'état dans la réponse renvoyée par la fonction Firebase.

2
user835611 14 mars 2019 à 11:20