The target

  • A simple Ajax implementation
  • A brief introduction to the use of FETCH

The main points of

What is the Ajax

  • The core is XMLHTTPRequest

  • AJAX = Asynchronous JavaScript and XML.

  • AJAX is not a new programming language, but a new way to use existing standards.

  • AJAX is the art of exchanging data with a server and updating parts of a web page without reloading the entire page.

Common browser request/response headers/error code parsing

The specific meaning of each parameter can be found at 😛

Common request header

  • :method: GET
  • :path:
  • :scheme: https
  • accept: application/json, text/plain
  • accept-encoding: gzip, deflate, br
  • cache-control: no-cache
  • cookie: deviceId=c12;
  • origin:
  • referer:
  • The user-agent: Mozilla / 5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1

Commonly used the response headers

  • access-control-allow-credentials: true
  • Access-control-allow-origin: https://domian/service // The browser only allows requests for resources from the current domain and does not trust resources from other domains
  • content-encoding: gzip
  • content-type: application/json; charset=UTF-8
  • date: Thu, 06 Aug 2020 08:15:05 GMT
  • set-cookie: sess=QvrAQ0Cq+EcDQQPTer2XHlv4fhIRaW/YCb/e4pz/I+uSfZtum4dPp9q4HJL5o+GWuDXHXQLQF2JrIgwzZPaZHWal4qYZy/cfW0Sle/fyB/w=; domain=.yuanfudao.biz; path=/; HttpOnly
  • set-cookie: userid=172270653; domain=.yuanfudao.biz; path=/; HttpOnly
  • status: 200

Commonly used status

  • 200 get success
  • 201 post success
  • 301 permanent redirect
  • 302 Temporary redirect
  • 304 Negotiation cache server file is not modified
  • 400 The client request has a syntax error and cannot be recognized by the server
  • 403 The server is requested but refuses to provide service, possibly across domains
  • 404 requested resource not found
  • Method requested by 405 is not allowed
  • 500 An unexpected error occurs on the server

Let’s start with a simple implementation

When readyState changes, the onReadyStatechange event is emitted
Graph TD xhr. onReadyStatechange --> 0: request not initialized --> 1: server connection established --> 2: request received --> 3: request processing --> 4: request completed and response ready

let xhr = new XMLHttpRequest();
xhr.open('GET'.'http://domain/service');

// Request State change event Changed from 0 to 4
xhr.onreadystatechange = function () {
    // request completed?
    if(xhr.readyState ! = =4) return;

    if (xhr.status === 200) {
        // request successful - show response
        console.log(xhr.responseText);
    } else {
        // request error
        console.log('HTTP error', xhr.status, xhr.statusText); }};// xhr.timeout = 3000; // 3 seconds
// xhr.ontimeout = () => console.log('timeout', xhr.responseURL);
// start request
xhr.send();
❔ why send methods are processed last
Copy the code

fetch

The 🌐 browser has a new API with promises built in to handle responses through the then method

  • Cookies are not included by default
  • Error does not reject
  • Timeout Settings are not supported
  • AbortController is needed to abort fetch

Look at the example without ink

fetch('http://domain/service', {
    method: 'GET'.credentials: 'same-origin' // Control before sending cookies and two values include
}).then(response= > {
    if(response.ok) {
        return response.json()
    }
    throw new Error('http error')
}).then(json= > { // chain call
    console.log(json)
}).catch(error= > {
    console.error(error)
})

// It is not supported to set the timeout directly, you can implement it with promise
function fetchTimeout(url, init, timeout = 3000) {
    return new Promise((resolve, reject) = > {
        fetch(url, init)
            .then(resolve) // For example, after 1000ms, the request response is completed, and the state of promise is changed to pity; after 3000ms, the final result will not be modified, and the state of Pormise is irreversible
            .catch(reject);
        setTimeout(reject, timeout); })}Copy the code

How do I abort fetch ❔


/ / suspend the fetch
const controller = new AbortController();
fetch(
        'http://domain/service', {
            method: 'GET'.signal: controller.signal
        })
    .then(response= > response.json())
    .then(json= > console.log(json))
    .catch(error= > console.error('Error:', error));

controller.abort();
Copy the code

How is fetch implemented ❓ using TS ❗

interface IOptions {
    url: string, type? :'GET' | 'POST'.data: any, timeout? : number }// Process the queryString parameter of the GET request
function formatUrl(object) {
    // a=xxx&b=xxx querystring
    let dataArr = []
    for(let key in object) {
        dataArr.push(`${key}=The ${encodeURIComponent(object[key])}`)}return dataArr.join('&')}export function ajax(options: IOptions = {
    url: ' ',
    type: 'GET',
    data: {},
    timeout: 3000
}) {
    return new Promise((resolve, reject) = > {
        // Prevent bypass type checking ajax({} as any) from being used in this way
        if(! options.url) {return
        }

        const dataToQueryString = formatUrl(options.data)
        let timer = null
        let xhr = null

        // Request processing timed out
        const onStateChange = () = > {
            xhr.onreadystatechange = () = > {
                if (xhr.readyState === 4) {
                    clearTimeout(timer);
                    if (
                        (xhr.status >= 200 && xhr.status < 300) ||
                        xhr.status === 304
                    ) {
                        resolve(xhr.responseText);
                    } else{ reject(xhr.status); }}}; };if ((window as any).XMLHttpRequest) {
            xhr = new XMLHttpRequest
        } else {
        / / compatible with IE
            xhr = new ActiveXObject('Microsoft.XMLHTTP')}if (options.type.toUpperCase() === 'GET') {
            xhr.open('GET'.`${options.url}?${dataToQueryString}`);
            onStateChange();
            xhr.send();
        } else if (options.type.toUpperCase() === 'POST') {
            xhr.open('POST', options.url);
            xhr.setRequestHeader(
                'ContentType'.'application/x-www-form-urlencoded'
            );
            onStateChange();
            xhr.send(options.data);
        }
        
        // Request timeout processing
        if (options.timeout) {
            timer = setTimeout(() = > {
                xhr.abort();
                reject('timeout'); }, options.timeout); }})}Copy the code

➰ Happy times go by very quickly, and it’s time to say goodbye ➰