我正在尝试与一个编码相当糟糕、速度极慢的网站进行交互。我将用一个例子来说明我遇到的问题:
在这个网页上有两个选择框,第一个用于选择一个国家,在更改时向one服务器发出AJAX请求,然后one服务器返回一个城市列表。此列表用于填充第二个选择框。现在的问题是,我可以使用phanomtjs的页面对象中的evaluate函数来迭代第一个选择框并选择正确的选项。但在此之后,我必须等待n秒,才能填充第二个框。目前,我已经通过设置一个计时器来“解决”这个问题,在从第二个框中选择城市之前等待25秒。然而,这是一个非常糟糕的解决方案。首先,25秒在所有情况下都不够长,所以有时它会超时并失败。第二个问题是,在大多数情况下,25秒太长了。
所以我必须找到一种方法来等待第二个盒子被填充。首先,我认为我可以在evaluate函数中使用setInterval来测试是否填充了选择框。这是可行的,但有一个问题,因为setInterval是异步的,所以使用这种方法我无法确定是否可以做出正确的选择。为了说明我的意思,下面的代码是在我不需要等待的情况下是如何工作的:
var retval = page.evaluate(function () {
return selectOption('select_id',
info['country']);
});
该selectOption是一个遍历select元素的函数,直到找到正确的option元素,如果失败,则返回false,然后该返回值由求值函数返回,以便我可以检查它是否有效。
另一种选择是只在网页上下文中使用setInterval进行等待,然后在失败时引发和异常。我试过这样做,但我似乎无法捕捉到网站范围之外的异常。PhantomJS将异常转储到终端中,但我无法拦截它。
有什么办法可以解决这个问题吗?或者我应该只使用固定等待时间选项?
编辑:我试着使用page.onError,但它似乎没有被使用。
发布于 2014-02-06 08:25:10
我还需要找出evaluated函数中是否抛出了异常。我设法做到了这一点,添加了另一个层,用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,那么我会使用context对象。有关如何将变量参数传递给函数的不同方法,请查看问题:"JavaScript variable number of arguments to function"。
https://stackoverflow.com/questions/10600049
复制