javascript - Waiting for an element without setTimeout in PhantomJS -


i'm writing function wait element, here function:

function waitforelement(query){     var res="null";     var start=date.now();     do{         res=page.evaluate(function(query) {             return document.queryselector(query)+"";         }, query);     } while (res==="null" && date.now()-start<=100000);     console.log(date.now()-start);     console.log(res.tostring());     return res!=="null"; } 

in page.open(), call function , result "null". if put function call in settimeout(), works.

settimeout(function(){     page.render('afterlogin.png');     waitforelement('ul.coach li');     console.log('exit');     phantom.exit(); }, 50000); 

can explain me happened here?

javascript single-threaded. since you're doing busy wait, you're blocking execution of page loading , page javascript. not possible wait synchronously in phantomjs. have use recursive , asynchronous approach such shown in waitfor.js phantomjs examples folder:

/**  * wait until test condition true or timeout occurs. useful waiting  * on server response or ui change (fadein, etc.) occur.  *  * @param testfx javascript condition evaluates boolean,  * can passed in string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or  * callback function.  * @param onready when testfx condition fulfilled,  * can passed in string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or  * callback function.  * @param timeoutmillis max amount of time wait. if not specified, 3 sec used.  */ function waitfor(testfx, onready, timeoutmillis) {     var maxtimeoutmillis = timeoutmillis ? timeoutmillis : 3000, //< default max timout 3s         start = new date().gettime(),         condition = false,         interval = setinterval(function() {             if ( (new date().gettime() - start < maxtimeoutmillis) && !condition ) {                 // if not time-out yet , condition not yet fulfilled                 condition = (typeof(testfx) === "string" ? eval(testfx) : testfx()); //< defensive code             } else {                 if(!condition) {                     // if condition still not fulfilled (timeout condition 'false')                     console.log("'waitfor()' timeout");                     phantom.exit(1);                 } else {                     // condition fulfilled (timeout and/or condition 'true')                     console.log("'waitfor()' finished in " + (new date().gettime() - start) + "ms.");                     typeof(onready) === "string" ? eval(onready) : onready(); //< it's supposed once condition fulfilled                     clearinterval(interval); //< stop interval                 }             }         }, 250); //< repeat check every 250ms }; 

and can use this:

function waitforelement(selector, callback, timeout){     waitfor(function check(){         return page.evaluate(function(selector){             return !!document.queryselector(selector);         }, selector);     }, callback, timeout); }  settimeout(function(){     page.render('afterlogin.png');     waitforelement('ul.coach li', function(){         console.log('exit');         phantom.exit();     }, 100000); }, 50000); 

Comments