Reputation: 493
Is it possible to pass in a function into casper.evaluate()
var casper = require('casper').create({
//verbose: true,
logLevel: 'debug',
pageSettings: {
loadImage: false,
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4'
}
});
...
casper.then(function(){
var config = {};
config.test = function(a, b){
return a + b;
}
var extractInfo = this.evaluate(function(config) {
return value = config.test(1, 2);
}, config);
});
This is not working, so I am assuming no, but it seems like we should be able to since we can pass other things in like objects and arrays. If I can attach functions to config and pass that in that would be a HUGE benefit to CasperJS.
This way the helper functions could be modularized and separated into different includes etc before I run the scrape making the code super clean!
Upvotes: 1
Views: 510
Reputation: 61952
No, that is not directly possible. The documentation says the following:
Note: The arguments and the return value to the
evaluate
function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.Closures, functions, DOM nodes, etc. will not work!
JavaScript is of course very dynamic, so you can serialize a function and pass it as a string into the page context. Then you only need to evaluate it in the page context.
Let's take this for example a named (for simplicity) function add
:
function add(a, b){
return a + b;
}
You can pass it into the page context as a string:
this.evaluate(function(addFun){
// TODO: parse/evaluate function
}, add.toString());
var addInternal = new Function("a", "b", addFun + "; return add(a, b);");
produces
var addInternal = function anonymous(a, b) {
function add(a, b){
return a + b;
}; return add(a, b);
}
It's of course easier to simply evaluate the string.
eval(addFun)
which directly produces add
.
Closures can also be evaluated with this technique, but you need to provide the references from the outer scopes inside of the page context at the time of eval
.
If you want to do bigger utility functions, I would suggest that you look into how CasperJS includes the clientutils.js into each page (code).
It is done by having those function in an additional file which can be injected into the page. This can be done synchronously from a local file with casper.page.injectJs(filename)
or asynchronously from a remote file with casper.page.injectJs(filename, callback)
.
Of course, CasperJS provides settings so that those are injected into every page with either casper.options.clientScripts
or casper.options.remoteScripts
.
Upvotes: 2