Jsdom: Bagaimana Anda memuat skrip eksternal?

Dibuat pada 7 Jul 2017  ·  3Komentar  ·  Sumber: jsdom/jsdom

jsdom dapat menjalankan skrip yang sebaris di dalam tag <head> dokumen, tetapi bagaimana Anda membuatnya menjalankan skrip yang ditautkan ke dalam kepala dokumen melalui <script src=""> ?

Untuk opsi yang saya gunakan:

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

Info dasar:

  • Versi Node.js: 8.1.2
  • versi jsdom: 11.1.0

Kasus reproduksi minimal:

// 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>

Lengkapi contoh kerja minimum: https://github.com/cg433n/jsdom-test

Komentar yang paling membantu

Masalahnya di sini adalah bahwa DOMContentLoaded adalah peristiwa asinkron. Anda login sebelum memiliki kesempatan untuk terjadi. Anda harus menunggu sampai api; hanya dengan begitu document.write() Anda akan terjadi.

Sesuatu seperti ini mungkin harus bekerja:

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>`
  });
});

Semua 3 komentar

Masalahnya di sini adalah bahwa DOMContentLoaded adalah peristiwa asinkron. Anda login sebelum memiliki kesempatan untuk terjadi. Anda harus menunggu sampai api; hanya dengan begitu document.write() Anda akan terjadi.

Sesuatu seperti ini mungkin harus bekerja:

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>`
  });
});

Saya melihat! Kalian luar biasa - teruslah bekerja dengan baik!

Perhatikan: 2 fitur demo di atas berisiko.

retas FS

Atau, saya merekomendasikan menggunakan fs untuk membaca dan memuat kode js dari file, lihat Stackoverflow berdasarkan pendekatan @EricRicketts ' FS.read() di #3023 dan @Domenic 's addEventListener() di #1914. Demo kerja yang saya usulkan meliputi:

  • gunakan fs.readFileSync untuk memuat js eksternal ke dalam html sebagai string
  • loop untuk menangani beberapa file js eksternal
  • kasus penggunaan menembakkan fungsi js eksternal
  • gunakan kasus melewati variabel terminal ke node, lalu ke fungsi js eksternal

Ini kemungkinan akan mencegah Anda melakukan panggilan xhr/API dan karenanya hanya menyelesaikan sebagian masalah.

URL

Saya tidak dapat menemukan cara agar url berfungsi.
Idealnya, JSDOM minimal yang diperbarui memuat file external.js melalui demo kerja url akan diterima. :jantung:

Apakah halaman ini membantu?
0 / 5 - 0 peringkat