how to wait for element visibility in phantomjs

后端 未结 4 1477
予麋鹿
予麋鹿 2020-11-29 02:58

Users click this link:


Now I\'m simulating the click i

相关标签:
4条回答
  • 2020-11-29 03:24

    Heres a spin of Cybermaxs's answer:

    function waitFor ($config) {
        $config._start = $config._start || new Date();
    
        if ($config.timeout && new Date - $config._start > $config.timeout) {
            if ($config.error) $config.error();
            if ($config.debug) console.log('timedout ' + (new Date - $config._start) + 'ms');
            return;
        }
    
        if ($config.check()) {
            if ($config.debug) console.log('success ' + (new Date - $config._start) + 'ms');
            return $config.success();
        }
    
        setTimeout(waitFor, $config.interval || 0, $config);
    }
    

    Example of use:

    waitFor({
        debug: true,  // optional
        interval: 0,  // optional
        timeout: 1000,  // optional
        check: function () {
            return page.evaluate(function() {
                return $('#thediv').is(':visible');
            });
        },
        success: function () {
            // we have what we want
        },
        error: function () {} // optional
    });
    

    It's a little easier when you use a config variable.

    0 讨论(0)
  • 2020-11-29 03:26

    My approach for this scenario is to wait until "something" is done or true. I highly suggest you to test waitfor.js.

    demo.html

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
        <title>Test</title>
    </head>
    <body id="body">
    
        <div id="thediv">Hello World !</div>
    
        <script type="text/javascript">
            $('#thediv').hide();
            setTimeout(function () {
                $('#thediv').show();
            }, 3000);
    
        </script>
    </body>
    </html>
    

    demoscript.js

    var page = require('webpage').create();
    var system = require('system');
    
    function waitFor(testFx, onReady, timeOutMillis) {
        var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 5000, //< Default Max Timout is 5s
            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");
                        typeof (onReady) === "string" ? eval(onReady) : onReady();
                        clearInterval(interval);
                        //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
                    }
                }
            }, 500); //< repeat check every 500ms
    };
    
    if (system.args.length != 1) {
        console.log('invalid call');
        phantom.exit(1);
    } else {
        //adapt the url to your context
        page.open('http://localhost:40772/demo.html', function (status) {
            if (status !== 'success') {
                console.log('Unable to load the address!');
                phantom.exit();
            } else {
                waitFor(
                    function () {
                        return page.evaluate(function () {
                            return $('#thediv').is(':visible');
                        });
                    },
                    function () {
                        page.render('page.png');
                        phantom.exit();
                    }, 5000);
            }
        });
    }
    

    This script evaluate $('#thediv').is(':visible')(classic Jquery code) every 500 ms to check if the div is visible.

    0 讨论(0)
  • 2020-11-29 03:39

    PhantomJS runs asynchronously by default, causing problems like the one you describe above (where the script finishes before your results are ready)

    However there is nothing to stop you using it in a synchronous way.

    Just use phantom.page.sendEvent('mousemove') in a while loop. This will keep looping through the event pump until the webkit engine loads your page or processes any necessary browser events.

    var page = require('webpage').create();
    
    // Step 1: View item
    page.open('http://localhost/item3324.php');
    do { phantom.page.sendEvent('mousemove'); } while (page.loading);
    page.render('step1-viewitem.png');
    
    // Step 2: Add to cart
    page.evaluate(function() {$('#add-to-cart').click(); });
    do { phantom.page.sendEvent('mousemove'); } while (page.loading);
    page.render('step2-viewcart.png');
    
    // Step 3: Confirm contents
    page.evaluate(function() {$('#confirm-cart').click(); });
    do { phantom.page.sendEvent('mousemove'); } while (page.loading);
    page.render('step3-confirm.png');
    

    Note that page.loading can also be any other boolean condition, for example:

    do { phantom.page.sendEvent('mousemove'); } 
    while (page.evaluate(function() {return $("#panel").is(":visible");}));
    

    I discovered this approach while working on the triflejs.org project (the Internet Explorer version of phantom) trying to emulate calls to trifle.wait(ms) inside the PhantomJS environment.

    0 讨论(0)
  • 2020-11-29 03:42

    Inside page.evaluate(), use the self.loading property to test for doneness ....

    var fs = require('fs');
    path = '/path/to/file.html';
    address = 'http://google.com';    
    
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('Unable to access page');
        } else {
            var p = page.evaluate(function () {
                if(!self.loading){ // ah, such beauty
                  return document.documentElement.outerHTML;
                }
            });
        fs.write(path, p, 'w');
        }
        phantom.exit();
    });     
    
    0 讨论(0)
提交回复
热议问题