2

我正在尝试与一个编码相当糟糕且速度非常慢的网站进行交互。我将举例说明我遇到的问题:

在这个网页上有 2 个选择框,第一个用于选择国家,onchange 向网络服务器发出 AJAX 请求,然后返回城市列表。此列表用于填充第二个选择框。现在的问题是我可以使用 phanomtjs 页面对象中的评估函数来遍历第一个选择框并选择正确的选项。但在那之后,我必须等待 n 秒才能填充第二个框。目前,我已经通过设置计时器等待 25 秒,然后从第二个框中选择城市来“解决”这个问题。然而,这是一个非常糟糕的解决方案。首先,25 秒在所有情况下都不够长,所以有时它会超时而失败。第二个问题是,在大多数情况下,25 秒太长了。

所以我必须找到一种方法来等待第二个盒子被填充。起初我虽然可以在评估函数中使用 setInterval 来测试是否填充了选择框。这行得通,但有一个问题,因为 setInterval 是异步的,使用这种方法我失去了找出是否可以做出正确选择的能力。为了说明我的意思,下面的代码是当我不必等待时它是如何工作的:

var retval = page.evaluate(function () {
    return selectOption('select_id',
                        info['country']);
});

该 selectOption 是一个迭代 select 元素直到找到正确的选项元素的函数,如果失败则返回 false,然后由评估函数返回此返回值,以便我可以检查它是否有效。

另一种选择是在网页上下文中使用 setInterval 进行等待,如果失败则引发异常。我试过这样做,但我似乎无法捕捉到网站范围之外的异常。PhantomJS 在终端中转储异常,但我无法拦截。

有没有办法解决?还是我应该只使用固定等待时间选项?

编辑:我尝试使用 page.onError,但它似乎没有被使用。

4

1 回答 1

0

我还需要找出在评估函数中是否引发了异常。我设法通过添加另一个层来做到这一点,该层只是用 try-catch 包装了函数:

// Wrap a function (func) inside a try-catch block and return
// the exception if any. Otherwise return null. The ctx is a
// a bucket for all the variables to be passed to func.
var tryCatchWrapper = function(func, ctx) {        
    try {
        funct(ctx);
    }
    catch(e) {
        return e;
    }

    return null;
}

然后评估somefunction我这样使用它:

var error = page.evaluate(tryCatchWrapper, somefunction);
if (error) {
    handle error...
}

如果我想将参数传递给 func ,那么我使用上下文对象。有关如何将变量参数传递给函数的不同方法,请查看问题:“JavaScript variable number of arguments to function”

于 2014-02-06T08:25:09.910 回答