Кукловод ждал, пока страница и setTimeout не будут работать в облачных функциях Firebase - PullRequest
4 голосов
/ 05 ноября 2019

Я пытаюсь загрузить страницу, которую я размещаю на firebase, и превратить ее в pdf с помощью Puppeteer.
Она отлично работает только с HTML-страницей.
Теперь я получаю данные из firebase и показываю их в моемстраницы, поэтому мне нужно дождаться полной загрузки страницы, прежде чем я смогу создать PDF.
Это прекрасно работает, когда я тестирую его локально с помощью эмулятора firebase npm run serve.
Однако это не работает вВ облачных функциях settimout просто ждет, пока не истечет время ожидания функции.
Журналы показывают waitFor, а через некоторое время Function execution took 120002 ms, finished with status: 'timeout'.
Я пробовал так много вещей, что не знаю, что делать, и я 'Я начинаю думать, что это ошибка в облачных функциях.

import * as functions from 'firebase-functions';
// tslint:disable-next-line:no-duplicate-imports
import { VALID_MEMORY_OPTIONS } from 'firebase-functions';
// import * as puppeteer from 'puppeteer';

const runtimeOpts = {
  timeoutSeconds: 120,
  memory: VALID_MEMORY_OPTIONS[4],
};

// const cors = require('cors')({ origin: true });

export const generatePDF = functions
  .runWith(runtimeOpts)
  // .region('europe-west1')
  .https.onRequest(async (request: any, response: any) => {
    // cors(request, response, async () => {
    console.log(7);

    const hostname = request.hostname;

    let url = '';
    if (hostname === 'localhost') {
      url = 'http://localhost:5000';
    } else {
      url = 'https://myapp.firebaseapp.com';
    }

    const puppeteer = require('puppeteer');

    console.log('launch puppeteer');

    const browser = await puppeteer.launch({
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
    });
    // debug: {headless: false}

    console.log('new page');

    const page = await browser.newPage();

    console.log('goto');

    await page
      .goto(`${url}/report/A3p71Fl5GD98Sjks5BJg`)
      .catch((error: any) => {
        console.log(error);
        return response.send('Timeout1');
      });

    console.log('waitFor');

    // await page.waitFor(10000).catch((error: any) => {
    //   console.log(error);
    //   return response.send('Timeout2');
    // });

    await new Promise(resolve => setTimeout(resolve, 5000));

    // await page.waitForNavigation({
    //   waitUntil: 'networkidle0',
    // });

    // Wait for element to render
    // await page.waitForSelector('#end');

    // await page.waitFor(10000);

    console.log('create pdf');

    const pdf = await page.pdf({
      format: 'A4',
    });

    console.log('close browser');

    await browser.close();

    // response.setHeader('Content-Disposition', 'attachment; filename=customfilename.pdf');
    response.setHeader('Content-Disposition', 'filename=customfilename.pdf');
    return response.type('application/pdf').send(pdf);
    // });
  });

export const helloWorld = functions.https.onRequest(
  async (request: any, response: any) => {
    await new Promise(resolve => setTimeout(resolve, 5000));
    response.send('Hello from Firebase!');
  },
);

// function delay(ms: number) {
//   return new Promise(resolve => setTimeout(resolve, ms));
// }

package.json:

{
  "name": "functions",
  "scripts": {
    "lint": "tslint --project tsconfig.json",
    "build": "tsc",
    "serve": "npm run build && firebase serve",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "8"
  },
  "main": "lib/index.js",
  "dependencies": {
    "cors": "^2.8.5",
    "firebase-admin": "^8.7.0",
    "firebase-functions": "^3.3.0",
    "puppeteer": "^2.0.0"
  },
  "devDependencies": {
    "tslint": "^5.12.0",
    "typescript": "^3.6.3"
  },
  "private": true
}

tsconfig.json:

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "outDir": "lib",
    "sourceMap": true,
    "strict": true,
    "target": "es2017",
    "lib": ["dom"]
  },
  "compileOnSave": true,
  "include": ["src"]
}

1 Ответ

1 голос
/ 13 ноября 2019

Вы должны импортировать кукловодов вне вашей функции, чтобы firebase мог использовать их повторно. Также вам не нужно создавать тайм-ауты, но вы можете использовать await page.waitFor(5000); вместо этого. Я попытался создать минимальный пример для вашего варианта использования. Если вы по-прежнему сталкиваетесь с ошибками, перейдите в консоль функций Firebase и проверьте журналы, в которых должно быть указано, что не так.

Существует также вероятность того, что вы не включили биллинг для своей учетной записи Firebase - вв этом случае ваша функция не может получить доступ к сторонним хостам.

import * as functions from 'firebase-functions';
import * as puppeteer from 'puppeteer';

export const generatePDF = functions
    .runWith({ timeoutSeconds: 30, memory: "1GB" })
    .https.onRequest(async (request, response) => {

        const url = 'https://www.yoururl.com/';
        const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox'] });

        const page = await browser.newPage();
        await page.goto(url);
        await page.waitFor(5000);

        const pdf = await page.pdf({
            format: 'A4',
        });

        await browser.close();

        response.setHeader('Content-Disposition', 'filename=customfilename.pdf');
        return response.type('application/pdf').send(pdf);
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...