0

I have been porting my code to PhantomJs and have been having a hard time with using $.ajax in Jquery. My code runs perfectly when the function call is dropped. I am new-ish to JavaScript other than in webpages. Here is my shortened code:

var page = require('webpage').create();
console.log('required webpage');

page.onConsoleMessage = function(msg) {
    console.log(msg);
};
console.log('added message event handler')

page.open('', function() {
    console.log('page.opened \nnow in page context');
    page.render('opened.png');
    page.includeJs("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
        page.evaluate(function() {
            console.log('evaluating');

            function getMessages() {
                return new Promise((resolve, reject) => {
                    $.ajax({
                        url: 'https://www.example.com/myrequest.php',
                        type: 'POST',
                        data: {
                            mychar_id: 32,
                            offset: 0,
                            limit: 10
                        },
                        success: function(data) {
                            if (data.trim() === '') {
                                console.log("received null");
                                reject("Received null data");
                            } else {
                                resolve(data);
                            }
                        },
                        error: function(xhr, status, error) {
                            console.log('AJAX Error:', error);
                            reject(error);
                        }
                    });
                });
            }

            getMessages().then(data => {
                console.log(data);
            }).catch(error => {console.error(error);});

            console.log("extending jquery.");
            // JQuery stuff goes here.
            console.log('Final markup.')
            console.log(document.body.innerHTML);
        });
        page.render('done.png')
        console.log('exiting');
        phantom.exit();
      });
    });

However, when running this with phantomjs, all I see is a blank cursor and the only way to exit is with ^c. I have tried everything I can think of, moving functions, etc. but so far, no luck. I know my function works elsewhere. What can I do?

2
  • this is a very VERY old version of jQuery; strongly suggest you update if for no other reasons than security and speed jquery/1.6.1/ Commented Apr 22 at 21:48
  • Jeez, I had no idea! I must have selected the wrong CDN while I was writing. Thanks for pointing that out. Commented Apr 23 at 18:06

1 Answer 1

0

The code you're sharing appears to be using PhantomJS (a headless engine for running JavaScript in the browser without a graphical interface), and there are a few points where you might encounter problems. Here are some suggestions for potential errors and how to fix them:

Incorrect use of Promise within page.evaluate: Promises cannot be used directly within page.evaluate because the page.evaluate context runs in PhantomJS's virtual browser, and Promise is a modern feature that isn't fully supported in this context.

Solution: To handle promises within page.evaluate, you can use a callback approach or ensure that the asynchronous logic is well-organized so as not to interfere with the PhantomJS execution flow.

Problem with phantom.exit(): Using phantom.exit() may cause the process to terminate before page.evaluate or page.open completes. This method is asynchronous and runs outside the main program flow.

Solution: Ensure that phantom.exit() only runs after all operations have completed. This can be controlled by moving phantom.exit() inside the promise or after the last major operation.

Potential issue when using page.includeJs: Loading an external JavaScript file inside page.includeJs is also asynchronous. The JavaScript code that executes the AJAX request may not execute correctly if page.evaluate doesn't wait for the external library to fully load.

Solution: You can pass the callback function to page.includeJs to ensure the code runs after the jQuery file has successfully loaded.

Calling console.log inside page.evaluate: While this should work, keep in mind that the console.log inside page.evaluate runs in the context of the web page, not PhantomJS, so you'll need to listen for console messages properly.

var page = require('webpage').create();
console.log('required webpage');

page.onConsoleMessage = function(msg) {
    console.log(msg);
};
console.log('added message event handler');

page.open('', function() {
    console.log('page.opened \nnow in page context');
    page.render('opened.png');

    page.includeJs("https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
        console.log('jquery included');
        page.evaluate(function() {
            console.log('evaluating');

            function getMessages() {
                var deferred = new WebPage().create();
                deferred.content = new Promise(function(resolve, reject) {
                    $.ajax({
                        url: 'https://www.example.com/myrequest.php',
                        type: 'POST',
                        data: {
                            mychar_id: 32,
                            offset: 0,
                            limit: 10
                        },
                        success: function(data) {
                            if (data.trim() === '') {
                                console.log("received null");
                                reject("Received null data");
                            } else {
                                resolve(data);
                            }
                        },
                        error: function(xhr, status, error) {
                            console.log('AJAX Error:', error);
                            reject(error);
                        }
                    });
                });

                return deferred;
            }

            getMessages().then(data => {
                console.log(data);
            }).catch(error => {
                console.error(error);
            });

            console.log("extending jquery.");
            // JQuery stuff goes here.
            console.log('Final markup.');
            console.log(document.body.innerHTML);
        });

        page.render('done.png');
        console.log('exiting');
        phantom.exit();
    });
});
Sign up to request clarification or add additional context in comments.

3 Comments

Can you please point out specifically the code changes you posted as this looks very similar to the code the OP posted and my eyes are having challenges picking changes out
Unfortunately, this still doesn't run. I'm sure It's the function definition that is causing the problem, and you definitely fixed some issues, so thanks.
Problem: PhantomJS exits before the AJAX call finishes Your code: page.evaluate(function() { ... getMessages().then(...); // Async ... }); page.render('done.png'); phantom.exit(); // <-- Exits PhantomJS almost immediately after evaluate starts

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.