1

我在 PhantomJS 中使用 waitFor-Method 时遇到了一些麻烦。

这就是我想要做的:

  • 通过生成的 url 加载多个网页
  • 使用 jQuery 解析该页面中的一些链接
  • 将每个解析的链接存储在同一个数组中(在本例中,我将只记录它们)

我正在使用waitFor() -方法,所以我可以等到页面被评估。据我了解,此方法将使程序阻止继续,直到我作为参数传递的函数返回任何内容。

我的问题: 实际上程序在执行 waitFor 方法后不会继续运行。它只是卡住了。没有任何错误。我作为参数传递的函数将不会被执行……至少控制台中没有日志记录。

当我删除 waitFor-Methot 时,它会正确执行代码,但是我不能多次执行 handleSeriesPageListPage()-Method。我真的不太喜欢 js 和回调或异步方法处理。我想我犯了一些严重的错误,一些 javascript 专家将能够快速帮助我:)。

"use strict";
var page = require('webpage').create();
page.onConsoleMessage = function (msg) {
    console.log(msg);
};
var seriesPageBaseUrl = "https://www.example.com?pageid=";
var simpleBaseUrl = "https://www.example.com/";
var seriesPageIds = [0xx, 1xx];
var allSeriesUrls = [];


function handleSeriesPageListPage(url) {
    console.log("Open url: " + url);
    page.open(url, function (status) {
        console.log("status: " + status);
        if (status === "success") {
            waitFor(
                function () {
                    return page.includeJs("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function () {
                        console.log("Included JS");
                        return page.evaluate(function () {
                            console.log("evaluate result...");
                            $('.list_item').each(function () {
                                var seriesLink = jQuery(this).find("a").first().attr("href");
                                var seriesUrl = simpleBaseUrl + seriesLink;
                                console.log(seriesUrl);
                                return true;
                            });
                        });
                    });
                }
            );
        } else {
            phantom.exit(1);
        }
    });
}

function nextSeriesListPage() {
    var seriesPageId = seriesPageIds.shift();
    if (typeof seriesPageId === "undefined") {
        console.log(allSeriesUrls);
        phantom.exit(0);
    }
    var targetURL = seriesPageBaseUrl + seriesPageId;
    handleSeriesPageListPage(targetURL);
}

nextSeriesListPage();
4

1 回答 1

1

您使用的waitFor()功能不是处理异步任务的合适方法,您实际上误解了它的作用:

waitFor(testFx, onReady, timeOutMillis)

接受三个参数(第三个是可选的)。第一个参数是一个测试函数。它被重复执行,但每次都是同步的,直到它的返回值为true. 然后,执行作为第二个参数给出的函数。如果在第三个参数给定的时间段内(或默认为 3 秒)没有true返回值,则函数退出并显示日志消息'waitFor()' timeout

您只提供了一个参数;一个在没有返回值的情况下完成的函数(page.includeJs()基本上)。因此,waitFor()应在 3 秒后退出该timeout消息。

你真正想要达到的是

  • 等待页面加载
  • 然后注入 jQuery 脚本,然后等待,
  • 然后重新评估,然后等待,
  • 然后提取信息

这是四个异步任务。PhantomJS 规定的基本方法是在上一个回调函数中进行相应的下一步,从而产生四个嵌套回调。

由于这不是一个很好的模式(通常称为回调地狱),因此Promise模式已作为 Javascript 功能引入(或包含在多个库中)。

要了解如何将回调 API 重新表述为 Promise,请查看 如何将现有回调 API 转换为 Promise?

于 2017-04-02T16:03:00.870 回答