• Skip to main content
  • Select language
  • Skip to search
MDN Web Docs
  • Technologies
    • HTML
    • CSS
    • JavaScript
    • Graphics
    • HTTP
    • APIs / DOM
    • WebExtensions
    • MathML
  • References & Guides
    • Learn web development
    • Tutorials
    • References
    • Developer Guides
    • Accessibility
    • Game development
    • ...more docs
Learn web development
  1. MDN
  2. Learn web development
  3. JavaScript
  4. Client-side web APIs
  5. Fetching data from the server

Fetching data from the server

In This Article
  1. What is the problem here?
    1. Enter Ajax
  2. A basic Ajax request
    1. XMLHttpRequest
    2. Serving your example from a server
    3. Fetch
      1. So what is going on in the Fetch code?
    4. Aside on promises
    5. Which mechanism should you use?
  3. A more complex example
    1. Challenge: An XHR version of the Can Store
  4. Summary
  5. See also
Previous Overview: Client-side web APIs Next

 

Another very common task in modern websites and applications is retrieving individual data items from the server to update sections of a webpage without having to load an entire new page. This seemingly small detail has had a huge impact on the performance and behavior of sites, so in this article we'll explain the concept and look at technologies that make it possible, such as XMLHttpRequest and the Fetch API.

Prerequisites: JavaScript basics (see first steps, building blocks, JavaScript objects), the basics of Client-side APIs
Objective: To learn how to fetch data from the server and use it to update the contents of a web page.

What is the problem here?

Originally page loading on the web was simple — you'd send a request for a web site to a server, and as long as nothing went wrong, the assets that made the web page would be downloaded and displayed on your computer.

A basic representation of a web site architecture

The trouble with this model is that whenever you want to update any part of the page, for example to display a new set of products or load a new page, you've got to load the entire page again. This is extremely wasteful and results in a poor user experience, especially as pages get larger and more complex.

Enter Ajax

This led to the creation of technologies that allow web pages to request small chunks of data (such as HTML, XML, JSON, or plain text) and display them only when needed, helping to solve the problem described above.

This is achieved by using APIs like XMLHttpRequest or — more recently — the Fetch API. These technologies allow web pages to directly handle making HTTP requests for specific resources available on a server, and formatting the resulting data as needed, before it is displayed.

Note: In the early days, this general technique was known as Asynchronous JavaScript and XML (Ajax), because it tended to use XMLHttpRequest to request XML data. This is not normally the case these days (you'd be more likely to use XMLHttpRequest or Fetch to request JSON), but the result is still the same, and the term "Ajax" is still often used to describe the technique.

A simple modern architecture for web sites

The Ajax model involves using a web API as a proxy to more intelligently request data rather than just having the browser to reload the entire page. Let's think about the significance of this:

  1. Go to one of your favorite information-rich sites, like Amazon, YouTube, CNN, etc., and load it.
  2. Now search for something, like a new product. The main content will change, but most of the surrounding information, like the header, footer, navigation menu, etc., will stay the same.

This is a really good thing because:

  • Page updates are a lot quicker and you don't have to wait for the page to refresh, meaning that the site feels faster and more responsive.
  • Less data is downloaded on each update, meaning less wasted bandwidth. This may not be such a big issue on a desktop on a broadband connection, but it's a major issue on mobile devices and in developing countries that don't have ubiquitous fast Internet service.

To speed things up even further, some sites also store assets and data on the user's computer when they are first requested, meaning that on subsequent visits they use the local versions instead of downloading fresh copies when the page is first loaded. The content is only reloaded from the server when it has been updated.

A basic web app data flow architecture

We won't cover such storage techniques in this article; we'll discuss it in a future article later in the module.

A basic Ajax request

Let's look at how such a request is handled, using both XMLHttpRequest and Fetch. For these examples, we'll request data out of a few different text files, and use them to populate a content area.

This series of files will act as our fake database; in a real application we'd be more likely to use a server-side language like PHP, Python, or Node to request our data from a database. Here however we want to keep it simple, and concentrate on the client-side part of this.

XMLHttpRequest

XMLHttpRequest (which is frequently abbreviated to XHR) is a fairly old technology now — it was invented by Microsoft in the late 1990's, and has been standardized across browsers for quite a long time.

  1. To begin this example, make a local copy of ajax-start.html and the four text files — verse1.txt, verse2.txt, verse3.txt, and verse4.txt — in a new directory on your computer. In this example we will load a different verse of the poem (which you may well recognize) via XHR when it's selected in the drop down menu.

  2. Just inside the <script> element, add the following code. This stores a reference to the <select> and <pre> elements in variables, and defines an onchange event handler function so that when the select's value is changed, its value is passed to an invoked function updateDisplay() as a parameter.

    var verseChoose = document.querySelector('select');
    var poemDisplay = document.querySelector('pre');
    verseChoose.onchange = function() {
      var verse = verseChoose.value;
      updateDisplay(verse);
    };
  3. Let's define our updateDisplay() function. First of all, put the following beneath your previous code block — this is the empty shell of the function:

    function updateDisplay(verse) {
    };
  4. We'll start our function by constructing a relative URL pointing to the text file we want to load, as we'll need it later. The value of the <select> element at any time is the same as the text inside the selected <option> (unless you specify a different value in a value attribute) — so for example "Verse 1". The corresponding verse text file is "verse1.txt", and is in the same directory as the HTML file, therefore just the file name will do.

    However, web servers tend to be case sensitive, and the file name hasn't got a space in it. To convert "Verse 1" to "verse1.txt" we need to convert the V to lower case, remove the space, and add .txt on the end. This can be done with replace(), toLowerCase(), and simple string concatenation. Add the following lines inside your updateDisplay() function:

    verse = verse.replace(" ", "");
    verse = verse.toLowerCase();
    var url = verse + '.txt';
  5. To begin creating an XHR request, you need to create a new request object using the XMLHttpRequest() constructor. You can call this object anything you like, but we'll call it request to keep things simple. Add the following below your previous lines:

    var request = new XMLHttpRequest();
  6. Next, you need to use the open() method to specify what HTTP request method to use to request the resource from the network, and what its URL is. We'll just use the GET method here, and set the URL as our url variable. Add this below your previous line:

    request.open('GET', url);
  7. Next, we'll set the type of response we are expecting — which is defined by the request's responseType property — as text. This isn't strictly necessarily here — XHR returns text by default — but it is a good idea to get into the habit of setting this in case you want to fetch other types of data in the future. Add this next:

    request.responseType = 'text';
  8. Fetching a resource from the network is an asynchronous operation, meaning that you've got to wait for that operation to complete (e.g., the resource is returned from the network) before you can then do anything with that response, otherwise an error will be thrown. XHR allows you to handle this using its onload event hander — this is run when the load event fires (when the response has returned). When this has occurred, the response data will be available in the response property of the XHR request object.

    Add the following below your last addition. you'll see that inside the onload event handler we are setting the textContent of the poemDisplay (the <pre> element) to the value of the request.response property.

    request.onload = function() {
      poemDisplay.textContent = request.response;
    };
  9. The above is all setup for the XHR request — it won't actually run until we tell it to, which is done using the send() method. Add the following below your previous addition to complete the function:

    request.send();
  10. One problem with the example as it stands is that it won't show any of the poem when it first loads. To fix this, add the following two lines at the bottom of your code (just above the closing </script> tag) to load verse 1 by default, and make sure the <select> element always shows the correct value:

    updateDisplay('Verse 1');
    verseChoose.value = 'Verse 1';

Serving your example from a server

Some browsers (including Chrome) will not run XHR requests if you just run the example from a local file. This is because of security restrictions (for more on web security, read Website security).

To get around this, we need to test the example by running it through a local web server. To find out how to do this, read How do you set up a local testing server?

Fetch

The Fetch API is basically a modern replacement for XHR — it was introduced in browsers recently to make asynchronous HTTP requests easier to do in JavaScript, both for developers and other APIs that build on top of Fetch.

Let's convert the last example to use Fetch instead!

  1. Make a copy of your previous finished example directory. (If you didn't work through the previous exercise, create a new directory, and inside it make copies of xhr-basic.html and the four text files — verse1.txt, verse2.txt, verse3.txt, and verse4.txt.)

  2. Inside the updateDisplay() function, find the XHR code:

    var request = new XMLHttpRequest();
    request.open('GET', url);
    request.responseType = 'text';
    request.onload = function() {
      poemDisplay.textContent = request.response;
    };
    request.send();
  3. Replace all the XHR code with this:

    fetch(url).then(function(response) {
      response.text().then(function(text) {
        poemDisplay.textContent = text;
      });
    });
  4. Load the example in your browser (running it through a web server) and it should work just the same as the XHR version, provided you are running a modern browser.

So what is going on in the Fetch code?

First of all, we invoke the fetch() method, passing it the URL of the resource we want to fetch. This is the modern equivalent of request.open() in XHR, plus you don't need any equivalent to .send().

After that, you can see the .then() method chained onto the end of fetch() — this method is a part of Promises, a modern JavaScript feature for performing asynchronous operations. fetch() returns a promise, which resolves to the response sent back from the server — we use .then() to run some follow-up code after the promise resolves, which is the function we've defined inside it. This is the equivalent of the onload event handler in the XHR version.

This function is automatically passed the response from the server as a parameter when the fetch() promise resolves. Inside the function we grab the response and run its text() method, which basically returns the response as raw text. This is the equivalent of request.responseType = 'text' in the XHR version.

You'll see that text() also returns a promise, so we chain another .then() onto it, inside of which we define a function to receive the raw text that the text() promise resolves to.

Inside the inner promise's function, we do much the same as we did in the XHR version — set the <pre> element's text content to the text value.

Aside on promises

Promises are a bit confusing the first time you meet them, but don't worry too much about this for now. You'll get used to them after a while, especially as you learn more about modern JavaScript APIs — most of the newer ones are heavily based on promises.

Let's look at the promise structure from above again to see if we can make some more sense of it:

fetch(url).then(function(response) {
  response.text().then(function(text) {
    poemDisplay.textContent = text;
  });
});

The first line is saying "fetch the resource located at url" (fetch(url)) and "then run the specified function when the promise resolves" (.then(function() { ... })). "Resolve" means "finish performing the specified operation at some point in the future". The specified operation in this case is to fetch a resource from a specified URL (using an HTTP request), and return the response for us to do something with.

Effectively, the function passed into then() is a chunk of code that won't run immediately — instead, it will run at some point in the future when the response has been returned. Note that you could also choose to store your promise in a variable, and chain .then() onto that instead. the below code would do the same thing:

var myFetch = fetch(url);
myFetch.then(function(response) {
  response.text().then(function(text) {
    poemDisplay.textContent = text;
  });
});

Because the fetch() method returns a promise that resolves to the HTTP response, any function you define inside a .then() chained onto the end of it will automatically be given the response as a parameter. You can call the paraneter anything you like — the below example would still work:

fetch(url).then(function(dogBiscuits) {
  dogBiscuits.text().then(function(text) {
    poemDisplay.textContent = text;
  });
});

But it makes more sense to call the parameter something that describes its contents!

Now let's focus just on the function:

function(response) {
  response.text().then(function(text) {
    poemDisplay.textContent = text;
  });
}

The response object has a method text(), which takes the raw data contained in the response body and turns it into plain text, which is the format we want it in. It also returns a promise (which resolves to the resulting text string), so here we use another .then(), inside of which we define another function that dictates what we want to do with that text string. We are just setting the textContent property of our poem's <pre> element to equal the text string, so this works out pretty simple.

It is also worth noting that you can directly chain multiple promise blocks (.then() blocks, but there are other types too) onto the end of one another, passing the result of each block to the next block as you travel down the chain. This makes promises very powerful.

The following block does the same thing as our original example, but is written in a different style:

fetch(url).then(function(response) {
  return response.text()
}).then(function(text) {
  poemDisplay.textContent = text;
});

Many developers like this style better, as it is flatter and arguably easier to read for longer promise chains — each subsequent promise comes after the previous one, rather then being inside the previous one (which can get unwieldy). The only other difference is that we've had to include a return statement in front of response.text(), to get it to pass its result on to the next link in the chain.

Which mechanism should you use?

This really depends on what project you are working on. XHR has been around for a long time now and has very good cross-browser support. Fetch and Promises, on the other hand, are a more recent addition to the web platform, although they're supported well across the browser landscape, with the exception of Internet Explorer and Safari (which at the time of writing has Fetch available in its latest technology preview).

If you need to support older browsers, then an XHR solution might be preferable. If however you are working on a more progressive project and aren't as worried about older browsers, then Fetch could be a good choice.

You should really learn both — Fetch will become more popular as Internet Explorer declines in usage (IE is no longer being developed, in favor of Microsoft's new Edge browser), but you might need XHR for a while yet.

A more complex example

To round off the article, we'll look at a slightly more complex example that shows some more interesting uses of Fetch. We have created a sample site called The Can Store — it's a fictional supermarket that only sells canned goods. You can find this example live on GitHub, and see the source code.

A fake ecommerce site showing search options in the left hand column, and product search results in the right hand column.

By default, the site displays all the products, but you can use the form controls in the left hand column to filter them by category, or search term, or both.

There is quite a lot of complex code that deals with filtering the products by category and search terms, manipulating strings so the data displays correctly in the UI, etc. We won't discuss all of it in the article, but you can find extensive comments in the code (see can-script.js).

We will however explain the Fetch code.

The first block that uses Fetch can be found at the start of the JavaScript:

fetch('products.json').then(function(response) {
  if(response.ok) {
    response.json().then(function(json) {
      products = json;
      initialize();
    });
  } else {
    console.log('Network request for products.json failed with response ' + response.status + ': ' + response.statusText);
  }
});

This looks similar to what we saw before, except that the second promise is inside a conditional statement. In the condition we check to see if the response returned has been successful — the response.ok property contains a Boolean that is true if the response was OK (e.g. 200 meaning "OK"), or false if it was unsuccessful.

If the response was successful, we run the second promise — this time however we use json(), not text(), as we want to return our response as structured JSON data, not plain text.

If the response was not successful, we print out an error to the console stating that the network request failed, which reports the network status and descriptive message of the response (contained in the response.status and response.statusText properties, respectively). Of course a complete web site would handle this error more gracefully, by displaying a message on the user's screen and perhaps offering options to remedy the situation.

You can test the fail case yourself:

  1. Make a local copy of the example files (download and unpack the can-store ZIP file)
  2. Run the code through a web server (as described above, in Serving your example from a server)
  3. Modify the path to the file being fetched, to something like 'produc.json' (i.e. make sure it is mispelled)
  4. Now load the index file in your browser (e.g. via localhost:8000) and look in your browser developer console. You'll see a message along the lines of "Network request for products.json failed with response 404: File not found"

The second Fetch block can be found inside the fetchBlob() function:

fetch(url).then(function(response) {
  if(response.ok) {
    response.blob().then(function(blob) {
      objectURL = URL.createObjectURL(blob);
      showProduct(objectURL, product);
    });
  } else {
    console.log('Network request for "' + product.name + '" image failed with response ' + response.status + ': ' + response.statusText);
  }
});

This works in much the same way as the previous one, except that instead of using json(), we use blob() — in this case we want to return our response as an image file, and the data format we use for that is Blob — the term is an abbreviation of "Binary Large Object", and can basically be used to represent large file-like objects — such as images or video files.

Once we've successfully received our blob, we create an object URL out of it, using createObjectURL(). This returns a temporary internal URL that points to an object referenced inside the browser. These are not very readable, but you can see what one looks like by opening up the Can Store app, Ctrl-/Right-clicking on an image, and selecting the "View image" option (which might vary slightly depending on what browser you are using). The object URL will be visible inside the address bar, and should be something like this:

blob:http://localhost:7800/9b75250e-5279-e249-884f-d03eb1fd84f4

Challenge: An XHR version of the Can Store

We'd like you to have a go at converting the Fetch version of the app to use XHR, as a useful bit of practice. Take a copy of the ZIP file, and try modifying the JavaScript as appropriate.

Some helpful hints:

  • You might find the XMLHttpRequest reference material useful.
  • You will basically need to use the same pattern as you saw earlier in the XHR-basic.html example.
  • You will, however, need to add the error handling we showed you in the Fetch version of the Can Store:
    • The response is found in request.response after the load event has fired, not in a promise then().
    • About the best equivalent to Fetch's response.ok in XHR is to check whether request.status is equal to 200, or if request.readyState is equal to 4.
    • The properties for getting the status and status message are the same, but they are found on the request (XHR) object, not the response object.

Note: If you have trouble with this, feel free to check your code against the finished version on GitHub (see the source here, and also see it running live).

Summary

That rounds off our article on fetching data from the server. By this point you should have an idea of how to start working with both XHR and Fetch.

See also

There are however a lot of different subjects discussed in this article, which has only really scratched the surface. For a lot more detail on these subjects, try the following articles:

  • Ajax — Getting started
  • Using Fetch
  • Promises
  • Working with JSON data
  • An overview of HTTP
  • Server-side website programming
Previous Overview: Client-side web APIs Next

 

Document Tags and Contributors

Tags: 
  • API
  • Article
  • Beginner
  • CodingScripting
  • data
  • Fetch
  • JavaScript
  • Learn
  • XHR
 Contributors to this page: marcusgenrich, chrisdavidmills, Sheppy
 Last updated by: marcusgenrich, Jun 5, 2017, 11:08:10 PM
See also
  1. Complete beginners start here!
  2. Getting started with the Web
    1. Getting started with the Web overview
    2. Installing basic software
    3. What will your website look like?
    4. Dealing with files
    5. HTML basics
    6. CSS basics
    7. JavaScript basics
    8. Publishing your website
    9. How the Web works
  3. HTML — Structuring the Web
  4. Introduction to HTML
    1. Introduction to HTML overview
    2. Getting started with HTML
    3. What's in the head? Metadata in HTML
    4. HTML text fundamentals
    5. Creating hyperlinks
    6. Advanced text formatting
    7. Document and website structure
    8. Debugging HTML
    9. Assessment: Marking up a letter
    10. Assessment: Structuring a page of content
  5. Multimedia and embedding
    1. Multimedia and embedding overview
    2. Images in HTML
    3. Video and audio content
    4. From object to iframe — other embedding technologies
    5. Adding vector graphics to the Web
    6. Responsive images
    7. Assessment: Mozilla splash page
  6. HTML tables
    1. HTML tables overview
    2. HTML table basics
    3. HTML Table advanced features and accessibility
    4. Assessment: Structuring planet data
  7. CSS — Styling the Web
  8. Introduction to CSS
    1. Introduction to CSS overview
    2. How CSS works
    3. CSS syntax
    4. Selectors introduction
    5. Simple selectors
    6. Attribute selectors
    7. Pseudo-classes and pseudo-elements
    8. Combinators and multiple selectors
    9. CSS values and units
    10. Cascade and inheritance
    11. The box model
    12. Debugging CSS
    13. Assessment: Fundamental CSS comprehension
  9. Styling text
    1. Styling text overview
    2. Fundamental text and font styling
    3. Styling lists
    4. Styling links
    5. Web fonts
    6. Assessment: Typesetting a community school homepage
  10. Styling boxes
    1. Styling boxes overview
    2. Box model recap
    3. Backgrounds
    4. Borders
    5. Styling tables
    6. Advanced box effects
    7. Assessment: Creating fancy letterheaded paper
    8. Assessment: A cool-looking box
  11. CSS layout
    1. CSS layout overview
    2. Introduction
    3. Floats
    4. Positioning
    5. Practical positioning examples
    6. Flexbox
    7. Grids
  12. JavaScript — Dynamic client-side scripting
  13. JavaScript first steps
    1. JavaScript first steps overview
    2. What is JavaScript?
    3. A first splash into JavaScript
    4. What went wrong? Troubleshooting JavaScript
    5. Storing the information you need — Variables
    6. Basic in JavaScript — Numbers and operators
    7. Handling text — Strings in JavaScript
    8. Useful string methods
    9. Arrays
    10. Assessment: Silly story generator
  14. JavaScript building blocks
    1. JavaScript building blocks overview
    2. Making decisions in your code — Conditionals
    3. Looping code
    4. Functions — Reusable blocks of code
    5. Build your own function
    6. Function return values
    7. Introduction to events
    8. Assessment: Image gallery
  15. Introducing JavaScript objects
    1. Introducing JavaScript objects overview
    2. Object basics
    3. Object-oriented JavaScript for beginners
    4. Object prototypes
    5. Inheritance in JavaScript
    6. Working with JSON data
    7. Object building practise
    8. Assessment: Adding features to our bouncing balls demo
  16. Accessibility — Make the web usable by everyone
  17. Accessibility guides
    1. Accessibility overview
    2. What is accessibility?
    3. HTML: A good basis for accessibility
    4. CSS and JavaScript accessibility best practices
    5. WAI-ARIA basics
    6. Accessible multimedia
    7. Mobile accessibility
  18. Accessibility assessment
    1. Assessment: Accessibility troubleshooting
  19. Tools and testing
  20. Cross browser testing
    1. Cross browser testing overview
    2. Introduction to cross browser testing
    3. Strategies for carrying out testing
    4. Handling common HTML and CSS problems
    5. Handling common JavaScript problems
    6. Handling common accessibility problems
    7. Implementing feature detection
    8. Introduction to automated testing
    9. Setting up your own test automation environment
  21. Server-side website programming
  22. First steps
    1. First steps overview
    2. Introduction to the server-side
    3. Client-Server overview
    4. Server-side web frameworks
    5. Website security
  23. Django web framework (Python)
    1. Django web framework (Python) overview
    2. Introduction
    3. Setting up a development environment
    4. Tutorial: The Local Library website
    5. Tutorial Part 2: Creating a skeleton website
    6. Tutorial Part 3: Using models
    7. Tutorial Part 4: Django admin site
    8. Tutorial Part 5: Creating our home page
    9. Tutorial Part 6: Generic list and detail views
    10. Tutorial Part 7: Sessions framework
    11. Tutorial Part 8: User authentication and permissions
    12. Tutorial Part 9: Working with forms
    13. Tutorial Part 10: Testing a Django web application
    14. Tutorial Part 11: Deploying Django to production
    15. Web application security
    16. Assessment: DIY mini blog
  24. Express Web Framework (node.js/JavaScript)
    1. Express Web Framework (Node.js/JavaScript) overview
    2. Express/Node introduction
    3. Setting up a Node (Express) development environment
    4. Express tutorial: The Local Library website
    5. Express Tutorial Part 2: Creating a skeleton website
    6. Express Tutorial Part 3: Using a database (with Mongoose)
    7. Express Tutorial Part 4: Routes and controllers
    8. Express Tutorial Part 5: Displaying library data
    9. Express Tutorial Part 6: Working with forms
    10. Express Tutorial Part 7: Deploying to production
  25. Further resources
  26. Advanced learning material
    1. WebGL: Graphics processing
  27. Common questions
    1. HTML questions
    2. CSS questions
    3. JavaScript questions
    4. How the Web works
    5. Tools and setup
    6. Design and accessibility
  28. How to contribute