Tony Schumacher Tony Schumacher - 17 days ago 22
Node.js Question

Node + Promise + Phantom.JS - Strange Error

I am using Node and npm phantom to make screenshot of many webpages.
To save CPU I use one Phantom instance per process. In this instance I am opening a page, render it, close it and go on.

This works really great except when I am starting another process. In this case I get this error, when one process is done:

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: undefined is not an object (evaluating 'target[command.params[0]]')

Phantom instance:

function initPhantom(todos) {
phantom.create(['--ignore-ssl-errors=no'], {logLevel: 'error'})
.then(function (instance) {
var processId = instance.process.pid;
console.log("===================> instance: ", processId);
phInstance = instance;
webshot(0, todos);
});
}


Loop through URLs:

function webshot(id, shots) {
phInstance.createPage().then(function (_page) {
sitepage = _page;
sitepage.property('viewportSize', {width: 1024, height: 768});
WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36');
sitepage.setting("resourceTimeout", 4000);
return sitepage.open(shots[id].url);
})
.then(function (status) {
console.log("render %s / %s", id + 1, shots.length);
setTimeout(function () {
var image = 'temp_img/' + shots[id]._id + '.png';
sitepage.render(image, {format: 'png', quality: '30'}).then(function (finished) {
sitepage.close();
chekcImageinDb(shots[id], image);
if (id < shots.length - 1) {
id += 1;
webshot(id, shots);
} else {
console.log("===================> all done: %s files has been written", shots.length);
phInstances.shift();
if(phInstances.length < 1){
console.log("kill phantom ", phInstances);
//phInstance.exit();
}
}
});
}, 2000);
})
}


Any idea

-------- edit -----------

OK I tried your suggestions, same error. As you can see in the log, it only occurs after one process is done.

function webshot(id, shots) {
phInstance.createPage().then(function (_page, error) {
if(error){
console.log("first", error);
}
sitepage = _page;
sitepage.property('viewportSize', {width: 1024, height: 768});
WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36');
sitepage.setting("resourceTimeout", 4000);
return sitepage.open(shots[id].url);
}).catch(function(e) {
console.log(e);
}).then(function (status, error) {
if(error){
console.log(error)
}
console.log("render %s / %s", id + 1, shots.length);
setTimeout(function () {
var image = 'temp_img/' + shots[id]._id + '.png';
sitepage.render(image, {format: 'png', quality: '30'})
.then(function (finished, error) {
if(error){
console.log(error)
}
sitepage.close();
chekcImageinDb(shots[id], image);
if (id < shots.length - 1) {
id += 1;
webshot(id, shots);
} else {
console.log("===================> all done: %s files has been written", shots.length);
phInstances.shift();
if(phInstances.length < 1){
console.log("kill phantom ", phInstances);
//phInstance.exit();
}
}
}).catch(function(e) {
console.log(e);
});
}, 2000);
}).catch(function(e) {
console.log(e);
})
}


Here is the log file for two instances started nearly at the same time. Like I said, if just one process is running, everything works great.

enter image description here

Answer

I think you need to pass a 2nd callback function to your then function calls for the failure handlers. Depending on the interface, you may instead need to chain a .catch(function(){}) after your then() calls.