问题描述
我已经尝试并测试了 - 成功 - 幻影示例。但是,我很难通过模块实现它,主要是因为 page.evaluate
在回调中得到评估。
I have tried and tested - with success - the phantomjs example waitFor. However, I am having difficulty implementing it via the phantomjs-node module primarily because page.evaluate
gets evaluated in a callback.
PhantomJS 实施
page.open("http://twitter.com/#!/sencha", function () {
waitFor(function() {
// This here is easy to do as the evaluate method returns immediately
return page.evaluate(function() {
return $("#signin-dropdown").is(":visible");
});
}, function() {
console.log("The sign-in dialog should be visible now.");
phantom.exit();
});
}
});
然而,使用 phantomjs-node ,evaluate函数会返回一个返回的数据回调:
However, with phantomjs-node the evaluate function gets returned data in a callback:
page.evaluate(
function(){ /* return thing */ },
function callback(thing) { /* write code for thing */ }
)
使用 phantomjs-node ,如何在元素可见后才能在页面上运行函数?
Using phantomjs-node, how can I run a function on the page only after an element is visible?
如果上面的链接已经死了,这里是waitFor函数的实现
Just in case the link above is dead, here is the implementation of the waitFor function
/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 250); //< repeat check every 250ms
};
提前致谢。
推荐答案
今天遇到这个问题,以为我会分享我的解决方案。
Ran into this problem today, thought I'd share my solution.
// custom helper function
function wait(testFx, onReady, maxWait, start) {
var start = start || new Date().getTime()
if (new Date().getTime() - start < maxWait) {
testFx(function(result) {
if (result) {
onReady()
} else {
setTimeout(function() {
wait(testFx, onReady, maxWait, start)
}, 250)
}
})
} else {
console.error('page timed out')
ph.exit()
}
}
第一步是创建一个新的 wait
函数。它采用与原始 waitFor
函数相同的参数,但工作方式略有不同。在测试函数 testFx
的回调之后,我们必须递归地运行 wait
函数,而不是使用间隔。被触发了。另外,请注意,您实际上不需要传递 start
的值,因为它会自动设置。
The first step is creating a new wait
function. It takes the same parameters as the original waitFor
function, but works a little differently. Instead of using an interval, we have to run the wait
function recursively, after the callback from the test function testFx
has been triggered. Also, note that you don't actually need to pass in a value for start
, as it gets set automatically.
wait(function (cb) {
return page.evaluate(function ()
// check if something is on the page (should return true/false)
return something
}, cb)
}, function () { // onReady function
// code
}, 5000) // maxWait
在这个例子中,我正在为 testFx
设置回调用作回调 page.evaluate
,它根据是否能够在页面上找到某个元素返回true / false值。或者,您可以为 page.evaluate
创建回调,然后从中触发 testFx
回调,如下所示:
In this example, I'm setting the callback for testFx
function as the callback to page.evaluate
, which returns a true/false value based on whether or not it was able to find some element on the page. Alternatively, you could create your callback for page.evaluate
and then trigger the testFx
callback from it, as shown below:
wait(function (cb) {
return page.evaluate(function ()
// check if something is on the page (should return true/false)
return something
}, function(result) {
var newResult = doSomethingCrazy(result)
cb(newResult)
}
}, function () { // onReady function
// code
}, 5000) // maxWait
这篇关于使用phantomjs-node实现waitFor功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!