setTimeout in Phantom.js

14,379

page.evaluate() is the sandboxed page context of PhantomJS. It has no access to variables defined on the outside. If you need the timeout, then you need to do two calls to page.evaluate(), because you cannot return anything from a asynchronous function (explanation):

page.evaluate(function() {
    ...
    element.dispatchEvent( event );
}, function() {
    setTimeout(function() {
        page.evaluate(function() {    
            return document.documentElement.outerHTML
        }, function(html) {
            doSomething()
        })
    }, 5000)
})

Instead of using the second page.evaluate() call, you may shorten the code by directly accessing the content as defined here:

setTimeout(function() {
    page.get("content", function(content) {
        doSomething()
    })
}, 5000)
Share:
14,379

Related videos on Youtube

Nyxynyx
Author by

Nyxynyx

Hello :) I have no formal education in programming :( And I need your help! :D These days its web development: Node.js Meteor.js Python PHP Laravel Javascript / jQuery d3.js MySQL PostgreSQL MongoDB PostGIS

Updated on June 04, 2022

Comments

  • Nyxynyx
    Nyxynyx almost 2 years

    The code below wants Phantom.js to load the page, click on a button and wait for 5 seconds before returning the page's HTML code.

    Problem: However using setTimeout() to create the 5 seconds delay causes the page.evaluate function to return null to the callback function instead of the HTML.

    myUrl = 'http://www.google.com'
    
    var phantom = Meteor.npmRequire('phantom')
    phantom.create = Meteor.wrapAsync(phantom.create)
    phantom.create( function(ph) {
    
        ph.createPage = Meteor.wrapAsync(ph.createPage)
        ph.createPage(function(page) {
    
            page.open = Meteor.wrapAsync(page.open)
            page.open(listingUrl, function(status) {
                console.log('Page loaded')
    
                page.evaluate = Meteor.wrapAsync(page.evaluate)
                page.evaluate(function() {
    
                    // Find the button
                    var element = document.querySelector( '.search-btn' );
    
                    // create a mouse click event
                    var event = document.createEvent( 'MouseEvents' );
                    event.initMouseEvent( 'click', true, true, window, 1, 0, 0 );
    
                    // send click to element
                    element.dispatchEvent( event );
    
                    // Give page time to process Click event
                    setTimeout(function() {
                        // Return HTML code
                        return document.documentElement.outerHTML
                    }, 5000)
    
                }, function(html) {
    
                    // html is `null`
                    doSomething()
    
                })
            })
        })
    })
    

    Replacing setTimeout() with Meteor.setTimeout() causes another error:

    phantom stdout: ReferenceError: Can't find variable: Meteor