首页 > 解决方案 > Puppeteer - 有没有办法将函数作为参数传递给通过exposeFunction 加载的函数?

问题描述

我有一个使用 puppeteer 的节点 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);
  });
};

运行代码时,我得到的打印结果是: null 25000 1000

含义谓词(正在发送的函数)被识别为空。尝试了所有不同的方式(将其保存为函数/函数表达式/匿名函数,没有异步),没有任何效果。

当发送字符串而不是函数时,打印会打印字符串本身,而不是 null。

有什么我做错了吗?有没有办法绕过它?

谢谢

标签: javascriptnode.jspuppeteerevaluate

解决方案


看起来,暴露的函数,以及评估的函数,只能使用可序列化的参数,所以函数不能作为参数在 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], param1, param2);
});

await page.evaluate(() => {
    await window.waitUntil('foo', 25000, 1000);
});

推荐阅读