admin管理员组

文章数量:1134248

I'm trying to fetch a file and return its HTML using the Fetch API. However it's not as simple as I'd have imagined.

fetch('/path/to/file')
.then(function (response) {
    return response.body;
})
.then(function (body) {
    console.log(body);
});

This returns an object called ReadableByteStream. How do I use this to grab the HTML file content?

If I change the contents of /path/to/file to be a JSON string, and change the above to:

fetch('/path/to/file')
.then(function (response) {
    return response.json();
})
.then(function (json) {
    console.log(json);
});

it returns the JSON correctly. How do I do fetch HTML?

I'm trying to fetch a file and return its HTML using the Fetch API. However it's not as simple as I'd have imagined.

fetch('/path/to/file')
.then(function (response) {
    return response.body;
})
.then(function (body) {
    console.log(body);
});

This returns an object called ReadableByteStream. How do I use this to grab the HTML file content?

If I change the contents of /path/to/file to be a JSON string, and change the above to:

fetch('/path/to/file')
.then(function (response) {
    return response.json();
})
.then(function (json) {
    console.log(json);
});

it returns the JSON correctly. How do I do fetch HTML?

Share Improve this question edited Aug 26, 2024 at 18:26 informatik01 16.4k11 gold badges78 silver badges108 bronze badges asked Apr 14, 2016 at 19:01 dittoditto 6,27710 gold badges57 silver badges91 bronze badges 6
  • 4 this raises concerns: what do you intend to do with that HTML? because I hope it's not "inject it into my active document". Instead ask for data, in JSON form, and then build DOM around that, clientside, so that you know the user isn't loading potentially hacked and super unsafe blind HTML. – Mike 'Pomax' Kamermans Commented Apr 14, 2016 at 19:33
  • 12 @Mike'Pomax'Kamermans You are assuming the HTML was coming from a user. I return server side generated HTML to take advantage of strongly typed views created with a strongly typed server language. – Louise Eggleton Commented Jul 9, 2019 at 17:41
  • 1 And you trust your server? I certainly don't trust mine, I don't even own the hardware it runs on. Instead of asking for HTML, I can wholeheartedly recommend using morphdom instead: have your server generate the HTML but then generate a diff that you send to your client, and have them apply that diff to the active DOM with morphdom again. Smaller payloads, so things are more responsive, and safer, too. – Mike 'Pomax' Kamermans Commented Jul 9, 2019 at 17:46
  • 1 @Mike'Pomax'Kamermans Since JS is runnable in the console, can't the user inject just about anything in the active document anyway? – Denis G. Labrecque Commented Jul 21, 2020 at 2:27
  • 2 This does not make sense, you are generating the main webpage from the same server, and then requesting it another from the same server: of course you have to trust your server! Else you would not trust the original page neither! – algo Commented Jan 22, 2023 at 18:50
 |  Show 1 more comment

8 Answers 8

Reset to default 189

You can download the HTML with fetch() and then parse it with DOMParser API.

fetch('somePage.html')
  .then(response => {
    // When the page is loaded convert it to text
    return response.text()
  })
  .then(html => {
    // Initialize the DOM parser
    const parser = new DOMParser()

    // Parse the text
    const doc = parser.parseFromString(html, "text/html")

    // You can now even select part of that html as you would in the regular DOM
    // Example:
    // const docArticle = doc.querySelector('article').innerHTML

    console.log(doc)
  })
  .catch(error => {
     console.error('Failed to fetch page: ', error)
  })

You need to use the .text() method, instead of .json(). This converts the byte stream into plain text, which can be parsed by the browser as HTML.

you can return the response with .text(), and then render the page in the doc as you want.

function fetchHtml() {
  fetch('./file.html')
  .then((response) => {
    return response.text();
  })
  .then((html) => {
    document.body.innerHTML = html     
  });
}

Using Promise Chaining with .then() is an older way of coding fetches and responses. A more modern way would be to use async functions and await like the following:

async function fetchMyDocument() {      
  try {
    let response = await fetch('/path/to/file.html'); // Gets a promise
    document.body.innerHTML = await response.text(); // Replaces body with response
  } catch (err) {
    console.log('Fetch error:' + err); // Error handling
  }
}

And about the direct answer to the question, (like every other answer) .text() is used instead of .json() on the response.

It should be:

fetch('/path/to/file').then(function(response) {
    return response.text();
}).then(function(string) {
    console.log(string);
}).catch(function(err) {  
    console.log('Fetch Error', err);  
});
  • 1- call function fetch and add the path of the page.
  • 2- then convert the fetch data to text by function .text().
  • 3- then append the page component to your parent container.

       async function getAbout() {


    await fetch('./component/about.html').then(res => res.text()).then(data => {
    page_2.innerHTML = data;

     }).then(() => {
       
         // after fetch write js code here  
     })}

  • for fetch, component don't add <body> or <HTML> tag < just use other like <div> or other tags.

  • for better performance use async-await!.

Use this:

var fetchAndParse = async (url) => { let div = document.createElement("div"); div.innerHTML = await (await fetch(url)).text(); return div }

Today I wanted to know the length of all the OpenSource licenses. I ended up running a code like this one on https://opensource.org/licenses/ (remove .slice(0, 3) to map it onto all links):

var $$ = (x) => ([...document.querySelectorAll(x)])
var fetchAndParse = async (url) => { let div = document.createElement("div"); div.innerHTML = await (await fetch(url)).text(); return div }
var waitTimeout = async (duration) => { return new Promise((accept) => setTimeout(accept, duration)) }
var licenseArray = await Promise.all($$(".license-table--title a[href]").slice(0, 3).map(async (anchor, k) => {
  let text = await fetchAndParse(anchor.href).then(div => div.querySelector("#LicenseText, .entry-content").textContent.replace(/\s+/g, ' ').trim()).catch(error => { console.error(anchor.href, error); return '' })
  return [anchor.href.replace(/^.*\/([^/]+)\/?/, '$1'), anchor.textContent.length, text.length, anchor.textContent, { href: anchor.href, text }]
}))

You can use the hmpl-js package to load HTML from the server. It works on fetch, so it can help you avoid writing a bunch of code:

<div id="wrapper"></div>
<script src="https://unpkg.com/hmpl-js"></script>
<script>
const templateFn = hmpl.compile(
    `<div>
       { 
         {
           "src":"http://localhost:8000/api/test" 
         } 
       }
    </div>`
  );

  const wrapper = document.getElementById("wrapper");

  const obj = templateFn();

  wrapper.appendChild(obj.response);
</script>

or

import { compile } from "hmpl-js";

const templateFn = hmpl.compile(
  `<div>
     { 
       {
         "src":"http://localhost:8000/api/test" 
       } 
     }
  </div>`
);

const wrapper = document.getElementById("wrapper");

const obj = templateFn();

wrapper.appendChild(obj.response);

本文标签: javascriptReturning HTML with fetch()Stack Overflow