PNG is not being rendered using PhantomJS with mul

2019-02-27 11:54发布

问题:

var page = require('webpage').create();
var filepath = "/home/abc/" + "abc.html"; //create path to charts.html    
for (i = 0; i < 3; i++) { // make three attempts
    console.log("hi")
    page.open(filepath, function(status) {
      console.log(status);
      //if(status !== 'success') { //if not success, make another attempt
//        continue;
  //    }

      page.render('abc.png');
      phantom.exit();
    });
}    
phantom.exit();

running this code like this:

$ phantomjs hello.js

Q1: I am expecting abc.png to be generated in my home dir. However with current code it is not generated.

Q2: Adding the commented out if block back causes the code execution to become stuck. Why so ?

回答1:

You have three problems that are intertwined.

1. continue

continue is used to go to the next iteration of a loop construct such as for or while. That's not what you're doing here. There is no loop around continue in the local scope which means this is a syntax error.

There is a bug in PhantomJS 2 that doesn't show Syntax errors anymore and simply freezes. Run your favorite linter (jslint, jshint, eslint) to prevent such mistakes.

2. page.open() is asynchronous

You cannot use a loop to open multiple page one after another. page.open() is asynchronous. By calling it, you only initiate the load. Since it doesn't block on the next iteration you will overwrite the request with a new URL and the first request will never be completed, because a for-loop is much faster than a page request.

The only page that could potentially be loaded is the last one, but ...

3. Premature exiting

You're exiting too early. Since page.open() is asynchronous, the loop will run completely through without loading even one page completely. At the end you have a phantom.exit() which will exit PhantomJS immediately.


If you have to open a bunch of pages, use a recursive approach or a clever use of setTimeout(). You could also use the async's series() function to write it in a more sane way.

Example as a simple recursive function:

var page = require('webpage').create();
var filepath = "/home/abc/" + "abc.html"; //create path to charts.html    
function run(i){
    if (i <= 0) {
      return phantom.exit();
    }
    page.open(filepath, function(status) {
      console.log(status);
      if(status === 'success') { //if not success, make another attempt
        page.render('abc'+i+'.png');
      }
      run(i-1);
    });
}
run(3);