Skip to content

Instantly share code, notes, and snippets.

@joseym
Last active May 26, 2017 21:48
Show Gist options
  • Save joseym/1d01edbcc40a7698f55a to your computer and use it in GitHub Desktop.
Save joseym/1d01edbcc40a7698f55a to your computer and use it in GitHub Desktop.
waitFor port for `phantomjs-node`
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);
}
);
}
var PhantomJS = require('phantom');
var waitFor = require('./phantomjs-waitFor');
var util = require('util');
PhantomJS.create(function phantom(ph){
ph.createPage(function(page){
page.open('https://www.google.com', function(status){
if(status !== 'fail'){
// required for an example below
page.set('onUrlChanged', function(url){
page.url = url;
});
/**
* As a simple example lets say we want to render an image of the google home page
* only after the logo has loaded ... (not the best example, but you should get the idea)
* @callback cb - waitFor's testFx callback can pass the results to a callback
* or return the value directly, heres the callback example
*/
waitFor(function Test(cb){
page.evaluate(function(){
return document.getElementById("hplogo").outerHTML;
}, function(logo){
cb(logo)
});
}, function(err, pass){
if(pass){
page.render('./google.jpg', function(){
console.log("render complete");
ph.exit();
});
} else {
console.error(err);
ph.exit()
}
}, 3000)
/**
* And heres an example with a basic return
* ***
* *** Note that lack of a `cb` argument, if you include a `cb` arg
* *** and don't provide it then the `testFx` never passes
* ***
* Here we'll render a screenshot for every results page
*/
waitFor(function Test(){
return /google\.com\/webhp.+q=/g.test(page.url);
}, function(err, pass){
if(pass){
var match = page.url.match(/^http[s]?:\/\/www\.google\.com\/webhp\?.*start=(\d+)/i);
var badImageFileName = util.format("./results_page_%d.jpg", match ? (parseInt(match[1]) + 10)/10 : 1);
page.render(badImageFileName, function(){
console.log("render complete");
ph.exit();
});
} else {
console.error(err);
ph.exit()
}
}, 3000)
}
})
})
})
@murilozilli
Copy link

murilozilli commented May 26, 2017

this example didn't work for me using:
"phantom": "^4.0.3",
on a node controller normal get endpoint

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment