首页 > 解决方案 > Puppeteer Google Cloud Function Pub/Sub Trigger 无法打开浏览器

问题描述

我正在尝试在 GCP 中创建一个可以由 Pub/Sub 消息触发的 Puppeteer 函数。该函数是可调用的,但不会像预期的那样运行,并且一旦浏览器尝试初始化就会引发超时错误。触发器是否可能使用与 HTTP 触发器不同的 NodeJS 环境?

我对 NodeJS 也很陌生,所以如果问题非常明显,我提前道歉。

我为按预期运行的函数创建了一个 HTTP 触发器。在创建云函数时,我将下面的 Puppeteer 函数复制/粘贴到 index.js 中,但为了清楚起见,在示例中分开了两个触发器正在运行相同的函数。

木偶功能

const puppeteer = require('puppeteer');

scrapeUglyWebsite = () => {
    return new Promise(async(resolve, reject) => {
        await puppeteer.launch({
            headless: true,
            args: ['--no-sandbox']
        })
            .then(async (browser) => {
                const page = await browser.newPage();
                await page.goto('http://suzannecollinsbooks.com/', {waitUntil: 'load', timeout: 0})
                    .then(async () => {
                        //Wait for content to load
                        await page.waitForFunction('document.body !== null && document.body.innerText.includes(\'Jon Scieszka\')');
                        //Evaluate page contents
                        const dom_eval = await page.evaluate(() => document.body.innerText.includes("Here’s a picture of me with a rat"));
                        await browser.close();
                        resolve(dom_eval);
                    });
            }).catch((err) => {
                reject(err);
            });
    });
};

HTTP 触发器 - index.js

exports.cloudFunctionTest = (req, res) => {
    scrapeUglyWebsite()
        .then((results) => {
            if(results) {
                res.send('Suzanne Collins takes pictures with rats.');
            } else {
                res.send("Suzzane Collins doesn't take pictures with rats.");
            };
        })
        .catch((err) => {
            res.send(err.toString());
        });

发布/订阅触发器 - index.js

exports.cloudFunctionTest = (data, context) => {
    scrapeUglyWebsite()
        .then((results) => {
            if(results) {
                console.log('Suzanne Collins takes pictures with rats.');
            } else {
                console.log("Suzzane Collins doesn't take pictures with rats.");
            };
        })
        .catch((err) => {
            console.log(err.toString());
        });
};

包.json

{
  "name": "test",
  "version": "0.0.1",
  "engines": {
    "node": "8"
  },
  "dependencies": {
    "puppeteer": "^1.6.0"
  }
}

HTTP 触发器的行为与预期结果正确

Suzanne Collins takes pictures with rats.

Pub/Sub 触发器抛出以下错误,没有输出

TimeoutError: Timed out after 30000 ms while trying to connect to Chrome! The only Chrome revision guaranteed to work is r662092

标签: google-cloud-functionspuppeteergoogle-cloud-pubsub

解决方案


我知道这已经晚了,但发生 TimeoutError 的原因是云功能不会自动等待异步任务完成。所以 in exports.cloudFunctionTest,scrapeUglyWebsite()被调用但函数不等待承诺被履行,所以程序终止。因此错误

有关后台功能如何在 NodeJs 中工作的更多信息

为了让函数等待scrapeUglyWebsite(),您需要返回一个完成的承诺,scrapeUglyWebsite()并且结果代码完成。

就个人而言,我通过简单地将当前在我正在导出的函数中的代码包装在另一个异步函数中然后返回包装函数的承诺来让它工作。

async function wrapper() {
    try {
        const result = await scrapeUglyWebsite(); 
        if(results) {
            console.log('Suzanne Collins takes pictures with rats.');
        } else {
            console.log("Suzzane Collins doesn't take pictures with rats.");
        };
    } catch (err) {
        console.log(err.toString());
    }
}

然后在要导出的函数中:

exports.cloudFunctionTest = (data, context) => {
    return wrapper();
};

推荐阅读