2013-03-17 4 views
22

Mit PhantomJS, möchte ich einige JS injizieren, als ob es ein extra <script> Tag vor allen anderen <script> Tags wäre. Dies liegt daran, dass die Skripts auf der Seite einige Funktionen verwenden, die PhantomJS nicht besitzt, nämlich Function.prototype.bind und window.webkitRequestAnimationFrame. Ich habe eine JS-Datei mit benutzerdefinierten Implementierungen der beiden, und ich möchte, dass PhantomJS sie beim Ausführen der Skripts auf der Seite verwendet.PhantomJS: Injizieren eines Skripts vor anderen Skripten ausführen

Die Schwierigkeit ist, dass, wenn ich page.injectJs vor page.open mache, das Skript in eine leere Seite eingefügt wird und nicht auf die Seite übertragen wird, die geöffnet wird.

Alternativ, wenn ich page.injectJs nach page.open mache, ist es zu spät, da die JavaScript-Fehler (undefinierte Funktionen) bereits aufgetreten sind.

ich einen Weg gefunden zu haben, scheint zu funktionieren, aber es ist offensichtlich ein Hack:

page.onResourceReceived = function() { 
    page.injectJs('phantom-hacks.js') 
}; 

Dieses spritzt es viele Male (zweimal für jede Ressource, scheinbar), aber das ist okay, weil mein Skript idempotent . Allerdings würde ich gerne wissen, wie dies funktioniert: injizieren Sie es nur einmal und bevor irgendwelche Skripte auf der Seite ausgeführt werden.

Thanks :)

+0

warum nicht einen Hash mit allen Dateien, halten Sie, wo der Schlüssel die Datei injizieren wollen, ist und der Wert ist, ob es injiziert wurde oder nicht, und es, wenn wurde es dann nicht gespritzt injizieren? Oder Sie können den Ereignis-Listener einfach nach dem ersten Lauf stoppen? – Nonconformist

Antwort

23

Ich glaube nicht, dass es eine „richtige“ ist derart Skript zu injizieren andere als an Veranstaltungen Einhaken. Ich habe ein halbes Jahr damit verbracht, massiv mit PhantomJs zu arbeiten und habe keine Möglichkeit gefunden, etwas zu injizieren, bevor alle Fehler auftreten, aber nachdem die Seite fertig geladen wurde.

Ich würde versuchen, onInitialized, onLoadStarted, onLoadFinished durchlaufen. Innerhalb der Hooks würde ich page.evaluate() aufrufen, was nur DOM ändern würde, um diesen zusätzlichen Platz zu haben, den du magst.

Ich denke, einer von ihnen (die Haken) sollte Ihnen das richtige Timing geben, das Sie wollen.

Prost

+9

Die Verwendung von 'onInitialized' und' injectJs' (Übergabe des relativen Pfades zu den Polyfills) funktionierte in meinem Fall perfekt. –

+2

@MarcoLazzeri danke für deinen Kommentar, 'onInitialized' ist genau das, was ich für den gleichen Zweck brauchte. – haynar