Puppeteer - 有没有办法将函数作为参数传递给通过 ExposeFunction 加载的函数?

问题描述

我有一个使用 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());
                }

这里是导出函数waitUntil的内部js文件

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);
});