Javascript 使用phantomjs节点实现waitFor功能
我已经尝试并测试了phantomjs示例,并取得了成功。但是,我很难通过模块实现它,主要是因为Javascript 使用phantomjs节点实现waitFor功能,javascript,node.js,phantomjs,Javascript,Node.js,Phantomjs,我已经尝试并测试了phantomjs示例,并取得了成功。但是,我很难通过模块实现它,主要是因为page.evaluate在回调中进行计算 PhantomJS实现 page.open(“http://twitter.com/#!/sencha“,函数(){ waitFor(函数(){ //这很容易做到,因为evaluate方法会立即返回 返回page.evaluate(函数(){ 返回$(“#登录下拉列表”)。为(“:可见”); }); },函数(){ log(“登录对话框现在应该是可见的。”);
page.evaluate
在回调中进行计算
PhantomJS实现
page.open(“http://twitter.com/#!/sencha“,函数(){
waitFor(函数(){
//这很容易做到,因为evaluate方法会立即返回
返回page.evaluate(函数(){
返回$(“#登录下拉列表”)。为(“:可见”);
});
},函数(){
log(“登录对话框现在应该是可见的。”);
phantom.exit();
});
}
});
但是,使用phantomjs节点,evaluate函数在回调中获取返回的数据:
page.evaluate(
函数(){/*返回对象*/},
函数回调(thing){/*为thing编写代码*/}
)
使用phantomjs节点,如何仅在元素可见后才能在页面上运行函数
为了防止上面的链接失效,下面是waitFor函数的实现
/**
*等待测试条件为真或出现超时。等待有用
*在服务器响应或发生ui更改(fadeIn等)时。
*
*@param testFx计算为布尔值的javascript条件,
*它可以作为字符串传入(例如:“1==1”或“$”(“#bar”)。is(“:visible”)”或
*作为回调函数。
*@param onReady满足testFx条件时该怎么办,
*它可以作为字符串传入(例如:“1==1”或“$”(“#bar”)。is(“:visible”)”或
*作为回调函数。
*@param timeOutMillis是等待的最大时间。如果未指定,则使用3秒。
*/
函数waitFor(testFx、onReady、timeOutMillis){
var maxtimeOutMillis=timeOutMillis?timeOutMillis:3000,//<默认最大超时为3s
开始=新日期().getTime(),
条件=假,
间隔=设置间隔(函数(){
如果((新日期().getTime()-start
提前感谢。我已经为called编写了一个替代方法。它没有将所有函数调用和赋值转换为异步操作,而是在PhantomJS中执行整个函数 我认为你的问题可以这样解决:
phridge.spawn()
.then(function (phantom) {
return phantom.openPage(url);
})
.then(function (page) {
return page.run(selector, function (selector, resolve, reject) {
// this function runs inside PhantomJS bound to the webpage instance
var page = this;
var intervalId = setInterval(function () {
var hasBeenFound = page.evaluate(function (selector) {
return Boolean(document.querySelector(selector));
}, selector);
if (hasBeenFound === false &&
/* check if there is still some time left */) {
// wait for next interval
return;
}
clearInterval(intervalId);
if (hasBeenFound) {
resolve();
} else {
reject(new Error("Wait for " + selector + " timeout"));
}
}, 100);
});
})
.then(function () {
// element has been found
})
.catch(function (err) {
// element has not been found
});
今天遇到这个问题,我想和大家分享我的解决方案
// 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()
}
}
在本例中,我将testFx
函数的回调设置为对页面的回调。evaluate
,它根据是否能够在页面上找到某些元素返回真/假值。或者,您可以为页面创建回调。evaluate
然后触发testFx
校准从它返回,如下所示:
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
我最近创建了一个相当简单的节点模块,将waitFor移植到节点:
var async=require('async');
module.exports=waitFor;
/**
*waitFor用于的端口
*@见{@linkhttps://github.com/ariya/phantomjs/blob/master/examples/waitfor.js}
*@见{@linkhttps://github.com/sgentle/phantomjs-node}
*@callback testFx-Test函数将重复,直到达到true或超时限制
*@callback onReady-在“testFx”通过时触发。
*@param{(number | boolean | string)}[timeOut=false]-如果定义为false或字符串值为`forever`
*然后,“waitFor”将一直运行,直到“testFx”通过
*超时,否则以毫秒为单位传递一个数字。
*/
函数waitFor(testFx、onReady、超时){
var maxtimeOutMillis=typeof timeOut!=“未定义”?超时:5000//如果未定义,默认最大超时为5s
,start=new Date().getTime()
,isAsync=testFx.length>0
,通过=未定义
;
异步。直到(
函数测试(){
返回传递类型!==“未定义”;
},
功能动作(cb){
setTimeout(函数(){
如果(!maxtimeOutMillis | | maxtimeOutMillis=='forever'| | new Date().getTime()-start
如何使用phridge
生成PDF?与普通的幻影没有区别
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
var async = require('async');
module.exports = waitFor;
/**
* waitFor port used with
* @see {@link https://github.com/ariya/phantomjs/blob/master/examples/waitfor.js}
* @see {@link https://github.com/sgentle/phantomjs-node}
* @callback testFx - Test function, will repeat until true or timeout limit is reached
* @callback onReady - Fires if/when `testFx` passes.
* @param {(number|boolean|string)} [timeOut=false] - If defined and falsey or string value of`forever`
* then `waitFor` will run until `testFx` passes without
* timing out, otherwise pass a number in miliseconds.
*/
function waitFor(testFx, onReady, timeOut) {
var maxtimeOutMillis = typeof timeOut !== 'undefined' ? timeOut : 5000 // Default Max Timout is 5s if not defined
, start = new Date().getTime()
, isAsync = testFx.length > 0
, passing = undefined
;
async.until(
function Test() {
return typeof passing !== 'undefined';
},
function Action(cb) {
setTimeout(function(){
if (!maxtimeOutMillis || maxtimeOutMillis == 'forever' || new Date().getTime() - start < maxtimeOutMillis) {
// If a callback is passed to `testFx` we'll handle that.
function useCallback(){
passing = arguments[0]
return cb();
};
passing = (function(){
return (typeof(testFx) === "string" ? eval(testFx) : testFx).apply(this, arguments);
})(isAsync ? useCallback : undefined);
if(!isAsync) cb();
} else {
return cb(new Error('`waitFor` timeout'));
}
}, 250);
},
function Done(err) {
return (function(){
return (typeof(onReady) === "string" ? eval(onReady) : onReady).apply(this, arguments);
})(err, passing);
}
);
}