Übergeben von Argumenten an die anonyme Funktion innerhalb der Seite.includeJs() und page.evaluate()
Ein wenig hintergrund... ich bin ein wenig javascript und phantom.js also ich weiß nicht, ob dies ist ein javascript-oder phantom.js bug (feature?).
Folgende erfolgreich abgeschlossen ist (sorry für die fehlende Phantomspeisung.exit(), du musst nur Strg+c sobald Sie fertig sind):
var page = require('webpage').create();
var comment = "Hello World";
page.viewportSize = { width: 800, height: 600 };
page.open("http://www.google.com", function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
phantom.exit();
} else {
page.includeJs('http://code.jquery.com/jquery-latest.min.js', function() {
console.log("1: ", comment);
}, comment);
var foo = page.evaluate(function() {
return arguments[0];
}, comment);
console.log("2: ", foo);
}
});
Dies funktioniert:
page.includeJs('http://code.jquery.com/jquery-latest.min.js', function() {
console.log("1: ", comment);
}, comment);
Ausgabe: 1: Hello World
Aber nicht:
page.includeJs('http://code.jquery.com/jquery-latest.min.js', function(c) {
console.log("1: ", c);
}, comment);
Ausgabe: 1: http://code.jquery.com/jquery-latest.min.js
Und nicht:
page.includeJs('http://code.jquery.com/jquery-latest.min.js', function() {
console.log("1: ", arguments[0]);
}, comment);
Ausgabe: 1: http://code.jquery.com/jquery-latest.min.js
Blick auf das 2. Stück, das funktioniert:
var foo = page.evaluate(function() {
return arguments[0];
}, comment);
console.log("2: ", foo);
Ausgabe: 2: Hello World
Und so:
var foo = page.evaluate(function(c) {
return c;
}, comment);
console.log("2: ", foo);
Ausgabe: 2: Hello World
Aber nicht dieses:
var foo = page.evaluate(function() {
return comment;
}, comment);
console.log("2: ", foo);
Ausgabe:
ReferenceError: Can ' T find variable: Kommentar
phantomjs://Webseite.evaluate():2
phantomjs://Webseite.evaluate():3
phantomjs://Webseite.evaluate():3
2: null
Die gute Nachricht ist, ich weiß, was funktioniert und was nicht, aber wie wäre es mit etwas Konsistenz?
Warum der Unterschied zwischen includeJs
und evaluate
?
Welches ist der richtige Weg, um Argumente an eine anonyme Funktion?
- Was meinst du mit " es funktioniert nicht? Gibt es eine Fehlermeldung, schlechten Ausgang, oder etwas anderes?
- Eine minute, ich werde Bearbeiten, die mit der Ausgabe von jedem...
- Nice job posting details der einzelnen test-und Ausgang! Das verwirrt mich auch.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die heikle Sache zu verstehen, mit PhantomJS ist, dass es zwei ausführungskontexte - das Phantom Kontext, die lokal auf Ihrer Maschine und hat Zugriff auf die
phantom
Objekt undrequire
d-Modul und der remote-Kontext, dessen, was existiert, innerhalb derwindow
des headless browser und hat nur Zugriff auf die Dinge geladen, die Webseiten, die Sie laden überpage.load
.Meisten von dem Skript, das Sie schreiben wird ausgeführt, der Phantom Rahmen. Die wichtigste Ausnahme ist alles, was innerhalb
page.evaluate(function() { ... })
. Die...
hier ist ausgeführt im remote-Kontext, die in der Sandbox ohne Zugriff auf die Variablen und Objekte in Ihrem lokalen Kontext. Sie können verschieben von Daten zwischen den beiden Kontexten von:page.evaluate()
oderDie Werte so übergeben werden im wesentlichen serialisiert in jede Richtung - Sie können sich nicht über ein Komplexes Objekt mit Methoden, die nur ein Daten-Objekt wie a string oder ein array (ich weiß nicht die genaue Umsetzung, aber die Faustregel scheint zu sein, dass alles, was Sie die Serialisierung mit JSON übergeben werden können, in beide Richtungen). Sie nicht haben Zugriff auf Variablen außerhalb der
page.evaluate()
Funktion, als würden Sie mit standard-Javascript, nur die Variablen explizit übergeben Sie als Argumente.So, deine Frage: Warum der Unterschied zwischen includeJs und bewerten?
.includeJs(url, callback)
nimmt eine callback-Funktion, die ausgeführt wird, innerhalb der Phantom Kontext, offenbar erhalten die url als sein erstes argument. Zusätzlich zu seinen Argumenten, er Zugriff hat (wie jeder normale JavaScript-Funktion) auf alle Variablen in seiner umschließenden scope, einschließlichcomment
in deinem Beispiel. Es tut nicht nehmen Sie ein zusätzliches argument-Liste, nachdem die callback-Funktion -, wenn Sie aufcomment
innerhalb der callback, Sie verweisen auf ein außerhalb variable, keine Funktion-argument..evaluate(function, args*)
nimmt eine Funktion auszuführen, und null oder mehr Argumente übergeben werden, um es (in einigen serialisierte form). Sie müssen die Namen der Argumente in die Funktion Signatur, z.B.function(a,b,c)
oder verwenden Sie denarguments
- Objekt Zugriff auf Sie - Sie wird nicht automatisch die gleichen Namen haben wie die Variablen übergeben.Also der richtige Weg, um Argumente übergeben, ist anders für die Funktionen in diesen verschiedenen Methoden. Für
injectJs
, wird der callback aufgerufen werden, mit einer neuen Reihe von Argumenten (einschließlich zumindest der URL), also alle Variablen, die Sie zugreifen möchten, muss in der callback-den umschließenden scope (d.h. Sie haben Zugang zu Ihnen innerhalb der Funktion closure). Fürevaluate
, es gibt nur einen Weg, um pass in den Argumenten, die in den Argumenten übergebenevaluate
selbst (es gibt andere Möglichkeiten auch, aber Sie sind schwierig und lohnt sich nicht jetzt diskutieren, dieses feature ist verfügbar in PhantomJS selbst).