Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
449 views
Welcome To Ask or Share your Answers For Others

1 Answer

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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...