Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/471.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Puppeter等待page和setTimeout在Firebase云函数中不工作_Javascript_Typescript_Firebase_Google Cloud Functions_Puppeteer - Fatal编程技术网

Javascript Puppeter等待page和setTimeout在Firebase云函数中不工作

Javascript Puppeter等待page和setTimeout在Firebase云函数中不工作,javascript,typescript,firebase,google-cloud-functions,puppeteer,Javascript,Typescript,Firebase,Google Cloud Functions,Puppeteer,我正在尝试加载我在firebase上托管的页面,并使用Puppeter将其转换为pdf。 只需一个html页面即可使用。 现在我从firebase获取数据并将其显示在我的页面中,因此我需要等待页面完全加载,然后才能创建pdf。 当我使用firebase emulator对其进行本地测试时,它工作得很好npm run serve 但是,它在云函数中不起作用,settimout只会一直等待,直到函数为timedout。 日志显示waitFor,一段时间后函数执行耗时120002毫秒,状态为:“超时”

我正在尝试加载我在firebase上托管的页面,并使用Puppeter将其转换为pdf。
只需一个html页面即可使用。
现在我从firebase获取数据并将其显示在我的页面中,因此我需要等待页面完全加载,然后才能创建pdf。
当我使用firebase emulator对其进行本地测试时,它工作得很好
npm run serve

但是,它在云函数中不起作用,settimout只会一直等待,直到函数为timedout。
日志显示
waitFor
,一段时间后
函数执行耗时120002毫秒,状态为:“超时”

我尝试了很多我不知道该怎么做的事情,我开始认为这是云函数中的一个bug

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"]
}

您应该在函数之外导入Puppeter,以便firebase可以重用它。您也不需要创建超时,但可以使用
wait page.waitFor(5000)取而代之。我试图为您的用例创建一个最小的示例。如果您仍然遇到错误,请转到firebase functions控制台并检查日志,它们会告诉您出了什么问题

还有一种可能是您尚未启用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);
    });

与您的问题无关,但为什么要这样定义回调函数:
(请求:any,响应:any)
?您不必向下转换这些参数来键入
any
。TypeScript应该根据firebase函数提供的类型绑定自动获取它们的值。我最近经常看到有人这样做,我不知道为什么。因为tslint对此抱怨,这很烦人,我无条件地使用tslint,我从未见过它抱怨。除了Firebase CLI为您所做的之外,您是否对配置进行了其他操作?我非常好奇。这不应该是一个问题。你是对的,我删除了它,tslint没有抱怨,我使用vscode和prettier。我只看到那条黄线一次,并补充说:任何,现在不要看到它,奇怪。好的。顺便说一句,我从来没有遇到过使用setTimeout实现云中等待功能的问题。谢谢,我必须为此安装Puppeter类型?上周2.0.0版没有提供,但我会尝试一个旧版本。你不必,但它非常方便!它工作了吗?如果我查看firebase函数控制台日志,没有什么,只是一个超时。在这种情况下,我高度怀疑您超时的原因是您选择的URL。我复制粘贴了上面的确切代码(将URL调整到此处的页面),并创建了一个云函数。你可以在这里看到结果(加载需要几秒钟,但是你会得到PDF):但是如果我在本地模拟器中使用相同的url,它确实可以工作,在这里也可以工作:没有问题,有时甚至我的云功能也可以工作