preface

XMLHttpRequest is widely used in AJAX programming and is well known to developers. As a result, AJAX and XMLHttpRequest are no longer strictly distinguished, and they are considered interchangeable where possible.

Through the establishment of interactive Web sites and modern Web standards, AJAX is gradually being replaced by functions in JavaScript frameworks and the official Fetch API standard. There is a lot of documentation on how to use the XMLHttpRequest and Fetch APIS, but this article focuses on how to abort the XMLHttpRequest and Fetch API requests. You are welcome to read and give good examples from your own practice.

Ajax

Around 1998, the Outlook Web Access group wrote the first component that allowed client-side scripts to send HTTP requests (XMLHTTP). This component was originally part of Microsoft Exchange Server and quickly became part of Internet Explorer 4.0[2]. As a result, Outlook Web Access is widely regarded as the first successful commercial application to use Ajax technology, and has become a leader in many products, including Oddpost’s Webmail product.

It wasn’t until early 2005, however, that Jesse James Jarrett published an article about the technology that allows web pages to asynchronously update their content by sending data back and forth in XML format via Javascript, It was only when the technology was abbreviated as “AJAX” to stand for the original “Asynchronous JavaScript and XML” that AJAX was accepted by the masses.

An application that uses AJAX to dynamically modify a web page is called an AJAX application. An AJAX application can only send and retrieve the necessary data to the server, and use JavaScript on the client side to process the response from the server. Because there is a lot less data being exchanged between the server and the browser, the server responds faster. At the same time, much of the processing can be done on the requesting client machine, so the load on the Web server is reduced.

AJAX does not refer to a single technology, but rather organically leverages a series of related technologies. Although the name contains XML, the data format can actually be replaced by JSON to further reduce the amount of data. The client and server do not need to be asynchronous. Some Ajax-based derivative/ Composite technologies are also emerging, such as AFLAX.

XMLHttpRequest

Introduction to the

The XMLHttpRequest (XHR) object is used to interact with the server. With XMLHttpRequest, you can request a specific URL to retrieve data without refreshing the page. This allows the web page to update parts of the page without affecting the user’s actions.

As you can see from the object prototype inheritance diagram above, XMLHttpRequest actually inherits the EventTarget prototype object:

compatibility

XMLHttpRequest was originally invented by Microsoft as an ActiveX object in Internet Explorer 5.0 and can be accessed through JavaScript, VBScript, or any other scripting language supported by the browser. Mozilla developers later implemented a compatible version in Mozilla 1.0. Since then, Apple Has supported XMLHttpRequest in Safari 1.2, and Opera has announced XMLHttpRequest support since version 8.0. So to use XMLHttpRequest in Internet Explorer 6 and before (or, more safely, Internet Explorer 9 and before), do this:

If (window.xmlhttprequest) {//Firefox, Opera, IE7, and other browsers use native JavaScript objects var request = new XMLHttpRequest(); Var Request = new ActiveXObject(" microsoft.xmlhttp "); }Copy the code

In IE6-IE9, XMLHttpRequest is not supported:

use

XMLHttpRequest is also simple to use:

const xhr = new XMLHttpRequest(); // create an XHR object const method = 'GET'; / / set the request type const url = 'https://developer.mozilla.org/'; xhr.open(method, url, true); xhr.onreadystatechange = () => { if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { console.log(xhr.responseText) } else { console.error(xhr.responseText) } } xhr.send();Copy the code

You can make an asynchronous request in a web page with the above code. When the request responds, the onReadyStatechange event is emitted, which determines the value of the readyState property to determine whether the request responded properly, and then acts accordingly.

The XMLHttpRequest abort

XMLHttpRequest comes with abort method:

If the request has already been issued, the xmlHttprequest.abort () method terminates the request. When a request is terminated, its readyState is set to xmlHttprequest.unsent (0) and the status of the request is set to 0.

Call syntax:

xhrInstance.abort();
Copy the code

So abort an XMLHttpRequest request simply calls ABORT before the request is returned. Of course, in ES6 era development, HTTP request responses are wrapped as Promise objects by default, and direct xhrInstance operations are rare. The code posted below comes from an abort get request utility function on Stack Overflow:

function getWithCancel(url, token) { // the token is for cancellation
   var xhr = new XMLHttpRequest;
   xhr.open("GET", url);
   return new Promise(function(resolve, reject) {
      xhr.onload = function() { resolve(xhr.responseText); });
      token.cancel = function() {  // SPECIFY CANCELLATION
          xhr.abort(); // abort request
          reject(new Error("Cancelled")); // reject the promise
      };
      xhr.onerror = reject;
   });
};
Copy the code

Abort indicates the response result

Request code:

const sendXhrRequest = () = > {
    const xhr = new XMLHttpRequest(); // Create an XHR object
    ref.current = xhr;
    const method = 'GET'; // Set the request type
    const url = 'demo url';

    xhr.open(method, url, true);
    xhr.onreadystatechange = () = > {
      if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
        setUser(JSON.parse(xhr.responseText));
      } else {
        console.log(xhr.readyState, xhr.status); }}; xhr.send(); };Copy the code

The result is shown in the figure below, where the first request is a properly responded XHR request and the second request is a call with ABORT () (the authors add a 3s response delay to the interface to facilitate testing).

By printing the status code, you can see that the normal request experienced a completeHEADERS_RECEIVEDandLOADINGState, and the HTTP state is 200; Abort requests enter directlyDONEThe HTTP status code is 0.

Fetch

The birth of

Promise, a front-end asynchronous programming wizard, was born in 2015 with the release of ES6.

A Promise object represents a value that is not necessarily known when the Promise is created. It allows you to associate the eventual success return value or failure cause of an asynchronous operation with the appropriate handler. This allows asynchronous methods to return values as synchronous methods do: instead of returning the final value immediately, asynchronous methods return a promise to give the value to the consumer at some point in the future.

In the same year, Google officially launched the Fetch API on Chrome in compliance with the Promise specification, which eventually became an ECMAScript standard feature.

compatibility

You can see that fetch is supported by all “modern” browsers.

With XHR difference

The Fetch API makes it easier to make Web requests and process responses than the old XMLHttpRequest, which often requires additional logic (for example, to handle redirects). Fetch provides a generic definition of Request and Response (and other objects related to network requests). In the future, it can be used in more scenarios: whether it’s service workers, Cache apis, or other ways of handling requests and responses, or even anything that requires you to generate your own responses in your application.

use

Fetch differs from XMLHttpRequest in two main ways:

  1. When an HTTP status code representing an error is received, thefetch()Return to the Promise ofIt’s not marked reject,Even if the HTTP status code of the response is 404 or 500. Instead, it marks the Promise state as resolve (but returns the value of resolve)okProperty set to false), which is marked reject only when the network fails or the request is blocked.
  2. fetch Cookies will not be sent. Unless you use itcredentials 的Initialization options. After August 25, 2017, the default credentials policy has changed tosame-origin. Firefox has also been modified in version 61.0b13)

The basic syntax of fetch is:

Promise<Response> fetch(input[, init]);
Copy the code

A basic fetch request is simple to set up:

fetch('http://example.com/movies.json')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });
Copy the code

The code above initiates the HTTP protocol to get a JSON file and print it to the console. Fetch () writes only one argument: the resource URL address, and fetch() returns a Promise (a Response object) containing the Response result.

Fetch () takes a second optional argument, an init object:

  • method: Request method used, such asThe GET and POST.
  • headers: Request header information.
  • body: Requested body information: it may be oneBlob,BufferSource 、FormData,URLSearchParams] orUSVStringObject.
  • mode: Request mode, such asCors, no - corsorsame-origin.
  • credentials: The credentials of requests, for exampleOmit, same-origin, or omit anything include. This option must be provided in order to automatically send cookies within the current domain name.
  • cacheRequest cache mode:default,no-store,reload 、 no-cache ,force-cache oronly-if-cached 。
  • redirect: Available Redirect modes:follow(Automatic redirection),error(A redirection will terminate automatically and an error will be thrown), ormanual(Handle redirection manually).
  • referrer: a USVString can beNo - the referrer, ` ` clientOr a URL. The default isThe client.
  • referrerPolicy: specifies the HTTP header referer field. May be one of the following values:No - the referrer, No - the referrer - the when - downgrade, The origin, Origin - the when - cross - origin, unsafe-url .
  • integrity: includes the subresource integrity values of the request (for example:Sha256 - BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE =.

Fetch the abort

This is a slight weakness compared to XMLHttpRequest. Fetch does not really support abort yet, but provides experimental AbortController and AbortSignal interfaces to abort the fetch request

Browsers have begun adding experimental support for the AbortController and AbortSignal interfaces (also known as Abort APIS), allowing operations like Fetch and XHR to be terminated before they complete.

Through the compatibility test, it can be found that the alignment compatibility of domestic browsers is poor, and the mainstream browsers of the newer versions abroad are OK. So the AbortController and AbortSignal interfaces are still available at this stage, if you can ensure compatibility with specified browsers. It is also simple to use.

Here’s an example:

  const fetchRef = useRef<AbortController>();

  const sendFetchRequest = () = > {
    const controller = new AbortController();
    const signal = controller.signal;
    fetchRef.current = controller;

    fetch(url, { signal })
      .then(function (res) {
        return res.json();
      })
      .then(function (data) {
        setUser(data ?? []);
      })
      .catch(function (e) {
        console.error('Download error: ' + e.message);
      });
  };
  const abortFetchRequest = () = > {
    console.log('Fetch aborted'); fetchRef.current? .abort(); };Copy the code

The AbortController() constructor first creates an instance of the controller, and the abortController.signal property then gets a reference to its associated AbortSignal object.

When the fetch Request is initialized, AbortSignal is passed as an option to the request’s option argument ({signal} in the code above). This associates signal, controller, and fetch requests, allowing us to abort the FETCH request by calling abortController.abort (), so abortBtn’s event can be used to listen for abortcontroller.abort ().

Execution Result:

Abortcontroller.abort () : abortController.abort () : abortController.abort () : abortController.abort () : abortController.abort () : abortController.abort ()

prompt

  • whenabort()Is called,fetch()The Promise will throw oneAbortError object.
  • AbortController after abort is executed is always in the abort state. In this case, AbortController needs to be created again. Otherwise, AbortController requests cannot be executed.Failed to execute 'fetch' on 'Window': The user aborted a request.abnormal

conclusion

  • XMLHttpRequestAbort methods are provided to easily terminate XHR requests by simply fetching xhrInstance.
  • FetchOnly experimental ones are available at the momentAbortControllerandAbortSignalInterface to terminate the outgoing request. This experimental feature works fine if the browser supports it, but what if it doesn’t? The solution is simple and crude:Discard “obsolete” responsesFor details, see the author’s next article.
  • PromiseIs a finite state machine, the flow of states is irreversible, based onPromise+Specification of theFecth APIIt can terminate its own request process, not terminate itPromise, in fact,FecthAfter the request terminates, the return is still arejectedthePromise;

reference

  • AJAX
  • XMLHttpRequest
  • Fetch API
  • AbortController.AbortController()
  • Working With Fetch Api
  • fetch-polyfill
  • How to cancel a promise in javascript ?