问题描述
我有一个使用 puppeteer 的 node js 项目,我想在页面上下文中使用库 async-wait-until。 这个库接收一个函数作为参数,尝试运行它,直到它返回一个真值或超时。
问题是我收到以下错误: 错误:谓词不是函数 有谓词保存函数的变量的名称。
const waitUntil = require('async-wait-until');
// const waitUntil = require('./node_modules/async-wait-until/src/waitUntil.js');
await page.exposeFunction('waitUntil',waitUntil);
这里我正在尝试运行该函数
try {
await waitUntil(() => {
//Code should come here
return false;
},25000,1000);
console.log('Element Is Ready');
} catch (e) {
console.log('CATCH');
console.log(e.toString());
}
var DEFAULT_INTERVAL = 50;
var DEFAULT_TIMEOUT = 5000;
/**
* Waits for predicate to be truthy and resolves a Promise
*
* @param predicate Function Predicate that checks the condition
* @param timeout Number Maximum wait interval,5000ms by default
* @param interval Number Wait interval,50ms by default
* @return Promise Promise to return a callback result
*/
module.exports = function waitUntil(
predicate,timeout,interval
) {
var timerInterval = interval || DEFAULT_INTERVAL;
var timerTimeout = timeout || DEFAULT_TIMEOUT;
return new Promise(function promiseCallback(resolve,reject) {
var timer;
var timeoutTimer;
var clearTimers;
var doStep;
clearTimers = function clearWaitTimers() {
clearTimeout(timeoutTimer);
clearInterval(timer);
};
doStep = function doTimerStep() {
var result;
try {
console.log('running predicate function');
console.log(predicate);
console.log(timeout);
console.log(interval);
result = predicate();
console.log('ran predicate function');
if (result) {
clearTimers();
resolve(result);
} else {
timer = setTimeout(doStep,timerInterval);
}
} catch (e) {
clearTimers();
reject(e);
}
};
timer = setTimeout(doStep,timerInterval);
timeoutTimer = setTimeout(function onTimeout() {
clearTimers();
reject(new Error('Timed out after waiting for ' + timerTimeout + 'ms'));
},timerTimeout);
});
};
运行代码时,我得到的打印结果是: 无效的 25000 1000
含义谓词(正在发送的函数)被识别为空。 尝试了所有不同的方法(将其保存为函数/函数表达式/匿名函数,没有异步),没有任何效果。
当发送字符串而不是函数时,打印会打印字符串本身,而不是空值。
我做错了什么吗? 有没有办法绕过它?
谢谢
解决方法
看起来,暴露的函数以及求值的函数只能使用可序列化的参数,因此函数不能作为参数在 Node.js 和浏览器上下文之间传递。也许你可以尝试一个包装器和一个函数字典,这样你就可以将函数名作为字符串传输:
const waitUntil = require('async-wait-until');
const functions = {
foo() {
//Code should come here
return false;
},bar() {
//Code should come here
return false;
},};
await page.exposeFunction('waitUntil',async (functionName,param1,param2) => {
waitUntil(functions[functionName],param2);
});
await page.evaluate(() => {
await window.waitUntil('foo',25000,1000);
});