我正在尝试在GCP中创建一个Puppeteer函数,该函数可以由发布/订阅消息触发。该函数是可调用的,但未达到预期的效果,并且一旦浏览器尝试初始化,就会引发“超时错误”。触发器可能使用与HTTP触发器不同的NodeJS环境吗?
我对NodeJS也很陌生,所以如果问题很明显,我会提前道歉。
我已经为该函数创建了一个HTTP触发器,该触发器的行为符合预期。创建Cloud Function时,我将下面的Puppeteer Function复制/粘贴到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());
});
Pub / Sub Trgger-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());
});
};
package.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
答案 0 :(得分:0)
我知道这很晚,但是发生TimeoutError的原因是因为云功能不会自动等待异步任务完成。因此,在exports.cloudFunctionTest
中,scrapeUglyWebsite()
被调用,但是该函数不等待承诺被兑现,因此程序终止。因此错误
有关后台功能如何在NodeJ中工作的更多信息here
为了使函数等待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();
};