【问题标题】:Puppeteer: wait for Ajax call after page loadingPuppeteer:页面加载后等待 Ajax 调用
【发布时间】:2020-05-30 09:19:39
【问题描述】:

解决方案:

根据@pguardiario 的建议,以下拦截Ajax 调用并等待其完成:

  await page.waitForResponse('http://localhost:58080/', {timeout: 2000})
    .catch(() => {console.log('[puppeteer] Error')});

我有一个页面在页面加载后执行 Ajax 调用,我需要 puppeteer 等待该调用完成。在puppeteer : wait for ajax call after navigation 中,接受的答案使用await page.waitForSelector(cssSelector);,这在我目前的情况下不起作用,因为Ajax 调用的成功不会向页面添加任何新元素。这是一个关于实际页面功能的最小工作示例,其中包含一些 cmets:

index.html:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" charset="utf-8"></script>
  </head>
  <body>
  </body>
  <script charset="utf-8">
    $(document).ready(function() {
      // render data previously stored in localStorage
      console.log('Fetching page');
      // in reality it is fetching a JSON API endpoint, but for the purposes of this example, use /
      $.get("/")
      .fail(function () {
        // add an error element to the page
        console.log('Error');
      })
      .done(function () {
        // empty the table containing the data and rerender
        console.log('Success');
      })
      .always(function () {
        // puppeteer can now continue and check for error
        console.log('Done fetching page');
      });
    });
  </script>
</html>

test.js:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  page.on('console', consoleObj => console.log(consoleObj.text()));
  await page.goto('http://localhost:58080');
  // What to do to wait for the completion of the ajax call done after
  // document is ready?
  console.log('[puppeteer] Sleeping');
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.log('[puppeteer] Closing');
  await browser.close();
});

serve.js:

const http = require('http');
const fs = require('fs');

http.createServer(function (request, response) {
    fs.readFile('index.html', function(error, content) {
        response.writeHead(200, { 'Content-Type': 'text/html' });
        response.end(content, 'utf-8');
    });
}).listen(58080, 'localhost');

在一个终端中:

node serve.js

另一个:

node test.js

输出:

[puppeteer] Sleeping
Fetching page
Success
Done fetching page
[puppeteer] Closing

我希望 puppeteer 在没有预设超时的情况下等待打印“完成获取页面”的点。我控制页面本身的源代码,因此接受任何想法,即使是那些需要更改目标服务器的想法。例如,如果我在 Ajax 调用结束后添加一个隐藏的 DOM 元素,我可以使用await page.waitForSelector(cssSelector);。我想知道是否有更好的方法。

【问题讨论】:

  • 听起来 waitForResponse 就是你要找的东西。
  • 谢谢@pguardiario 这确实是我需要的!
  • 如果您发布答案我可以接受
  • YW。我会让你这样做,只需发布​​你最终得到的任何代码。

标签: javascript node.js ajax puppeteer


【解决方案1】:

我相信 puppeteer 有一个可以挂钩的加载事件。

所以是这样的:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  page.on('console', consoleObj => console.log(consoleObj.text()));
  page.on('load', await () => { //set listener before you go to the page.
     // Now do something...
  });
  await page.goto('http://localhost:58080');
  // What to do to wait for the completion of the ajax call done after
  // document is ready?
  console.log('[puppeteer] Sleeping');
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.log('[puppeteer] Closing');
  await browser.close();
});

【讨论】:

  • 我在page.on('load', await () =&gt; 行得到一个SyntaxError: Malformed arrow function parameter list ...此外,ajax 调用将开始,并且肯定会在页面加载很久之后完成,所以这不能解决我的问题。
  • 好吧,我没有测试它,所以我不能确定确切的语法。此外,根据我的理解,从 page.goto 语句加载的 html 文档正在执行您在响应之前等待的另一个 Ajax 调用。没关系,onload 事件应该等到页面完成所有 Ajax 调用后才会触发事件。但似乎还有其他方法可以做到这一点:github.com/puppeteer/puppeteer/issues/598 也 waitForNavigation 是另一种可以提供帮助的方法。
  • 根据文档,语法是 page.once('load', () =&gt; console.log('Page loaded!')); 我这样做了,正如我所料,它甚至在我的 ajax 调用开始之前就被触发了。正如我所解释的,我的呼叫在页面加载后开始。它本身在$(document).ready注册。
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
  • 2012-09-30
  • 1970-01-01
相关资源
最近更新 更多