Jsdom: Wie laden Sie externe Skripte?

Erstellt am 7. Juli 2017  ·  3Kommentare  ·  Quelle: jsdom/jsdom

jsdom kann Skripte ausführen, die innerhalb des <head> -Tags des Dokuments eingebettet sind, aber wie bringen Sie es dazu, Skripte auszuführen, die im Dokumentkopf über <script src=""> verknüpft sind?

Für Optionen verwende ich:

{
    url: url,
    resources: 'usable',
    runScripts: 'dangerously',
}

Basisinformation:

  • Node.js-Version: 8.1.2
  • jsdom-Version: 11.1.0

Minimaler Reproduktionsfall:

// index.js
const request = require('request')
const jsdom = require('jsdom')
const {JSDOM} = jsdom
const url = 'http://localhost:8000'

request(url, (error, response, body) => {
  const options = {
    url: url,
    resources: 'usable',
    runScripts: 'dangerously',
  }

  const dom = new JSDOM(body, options)

  console.log(dom.window.document.body.children.length) // Expecting to see `1`
  console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
})
// external.js
document.addEventListener('DOMContentLoaded', () => {
  document.write('<h1>Hello world!</h1>')
})
<!-- index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>JSDOM test</title>
    <script src="external.js"></script>
  </head>
  <body>
  </body>
</html>

Vollständiges Mindestarbeitsbeispiel: https://github.com/cg433n/jsdom-test

Hilfreichster Kommentar

Das Problem hier ist, dass DOMContentLoaded ein asynchrones Ereignis ist. Du loggst dich ein, bevor es passieren kann. Sie müssen warten, bis es feuert; nur dann wird Ihr document.write() passieren.

So etwas sollte wahrscheinlich funktionieren:

const dom = new JSDOM(body, options)

dom.window.document.addEventListener('DOMContentLoaded', () => {
  // We need to delay one extra turn because we are the first DOMContentLoaded listener,
  // but we want to execute this code only after the second DOMContentLoaded listener
  // (added by external.js) fires.
  setImmediate(() => {
    console.log(dom.window.document.body.children.length) // Expecting to see `1`
    console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
  });
});

Alle 3 Kommentare

Das Problem hier ist, dass DOMContentLoaded ein asynchrones Ereignis ist. Du loggst dich ein, bevor es passieren kann. Sie müssen warten, bis es feuert; nur dann wird Ihr document.write() passieren.

So etwas sollte wahrscheinlich funktionieren:

const dom = new JSDOM(body, options)

dom.window.document.addEventListener('DOMContentLoaded', () => {
  // We need to delay one extra turn because we are the first DOMContentLoaded listener,
  // but we want to execute this code only after the second DOMContentLoaded listener
  // (added by external.js) fires.
  setImmediate(() => {
    console.log(dom.window.document.body.children.length) // Expecting to see `1`
    console.log(dom.window.document.body.innerHTML) // Expecting to see `<h1>Hello world</h1>`
  });
});

Ich verstehe! Ihr seid fantastisch – macht weiter so!

Hinweis: 2 Funktionen der obigen Demo sind riskant.

FS-Hack

Alternativ empfehle ich die Verwendung fs zum Lesen und Laden der js-Codes aus Dateien, siehe Stackoverflow basierend auf @EricRicketts ' FS.read() -Ansatz in #3023 und @Domenics addEventListener() in #1914. Die von mir vorgeschlagene Arbeitsdemo beinhaltet:

  • Verwenden Sie fs.readFileSync , um externe js als Zeichenfolgen in HTML zu laden
  • Schleife, um mehrere externe js-Dateien zu verarbeiten
  • Anwendungsfall des Auslösens externer js-Funktionen
  • Anwendungsfall der Übergabe von Terminalvariablen an den Knoten und dann an externe js-Funktionen

Dies wird Sie wahrscheinlich daran hindern, xhr / API-Aufrufe durchzuführen, und das Problem daher nur teilweise lösen.

URLs

Ich konnte nicht herausfinden, wie ich URLs zum Laufen bekomme.
Im Idealfall wäre ein aktualisiertes minimales JSDOM, das externe.js-Dateien über eine funktionierende URL-Demo lädt , willkommen. :Herz:

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen