1. XMLHttpRequest object

let xhr = new XMLHttpRequest()

1. Use XHR

  • Start by calling the open() method

    • Parameters: Boolean values for request type, request URL, and whether the request is asynchronous
    • The request is not actually sent, just ready to be sent.
    • Only same-origin urls can be accessed, that is, the same domain name, port, and protocol.
  • Send using the send() method

    • Parameters: Data sent as the request body, or null if the request body is not needed
    • The request is then sent to the server
  • To synchronize the request, the code waits for the server to respond before continuing, and the XHR object adds the following attributes

    • responseTextThe text returned as the body of the response
    • responseXMLIf the response content type is “text/ XML “or “application/ XML”, it is an XML DOM document containing the response data
    • statusThe HTTP status of the response
      • Need to check first
        • 2xx indicates successresponseTextorresponseXMLThere will be content
        • 304 indicates that the resource has not been modified and is fetched directly from the browser cache
    • statusTextHTTP status description of the response
  • An asynchronous request

    • The XHR object has onereadyStateProperty that represents the current stage in the request response process
      • 0: uninitialized, the open() method has not been called
      • 1: open, call open(), send() has not been called
      • 2: Yes, send() is called, but no response is received
      • 3: Some responses have been received
      • 4: Complete. All responses are received and available
    • Every time the value changes, it firesreadystatechangeEvent, you only care about the value of 4.
    let xhr = new XMLHttpRequest()
    xhr.onreadystatechange = function() {
      if(xhr.readyState === 4) {
        if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304){
          alert(xhr.responseText)
        }else {
          alert('error')
        }
      }
    }
    xhr.open("get"."test.txt".true)
    xhr.send(null)
    Copy the code
    • Cancel the asynchronous request before it is receivedxhr.abort()
      • When called, the XHR object stops firing events, preventing access to any respond-related properties on the object.

2. HTTP headers

  • Each request and response carries header fields, which are sent by default
    • Accept: Type of content that the browser can handle
    • Accept-Charset: Character set that the browser can display
    • Accept-Encoding: Type of compression encoding that the browser can handle
    • Accept-Language: Language used by the browser
    • Connection: Indicates the connection type between the browser and the server
    • Cookie: Cookie set on the page
    • Host: Domain of the page that sent the request
    • Referer: The page URI to send the request
    • User-Agent: browser user agent character string
  • throughsetRequsetHeader()Method sets the additional request header
    • Two arguments, the name and value of the header field
    • Call after open() and before send()
  • usegetResponseHeader()Method to get the response header from the XHR object
    • Parameter to get the name of the header
    • usegetAllResponseHeader()Returns all response header fields

3, GET request

  • The most common query method is used to query the server for some information.
  • If necessary, add the query string argument after the URL of the GET request.
  • Each name and value of the query string must be usedencodeURIComponent()coding
function addURLParam(url, name, value) {
  url += (url.indexOf("?") = = -1 ? "?" : "&")
  url += encodeURIComponent(name) + "=" + encodeURIComponent(value)
  return url
}
Copy the code

4. POST request

  • Used to send data to the server that should be saved.
  • Each POST request should carry the submitted data in the request body
  • The request body of a POST request can contain a very large amount of data, and the data can be in any format
  • Form submission can be simulated using XHR
    • theContent-TypeThe header is set toapplication/x-www-formulencoded
    • Create a string of the corresponding format
  • A POST request consumes more resources than a GET request and sends the same amount of data twice as fast as a POST request

5. XMLHttpRequest Level 2

1. FormData

  • Easy form serialization, easy to create form-like data to send through XHR
let data = new FormData()
data.append("name"."Nicholas")
Copy the code
  • append()Accepts two parameters, the key and the value, which are equivalent to the form field name and the value of that field.
  • Directly toFormDataThe constructor passes in a form element, or it can populate it with data from the form as key-value pairs
  • With FormData, you don’t need to explicitly set any request headers for XHR objects. You can configure the headers automatically based on the data type passed in by the FormData instance

2, the timeout

  • timeoutProperty to indicate the number of milliseconds to wait after sending the request and interrupt the request if the response is unsuccessful.
  • Trigger after timeouttimeoutEvents.
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
  if (xhr.readyState == 4) {
    try {
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
        alert(xhr.responseText);
      } else {
        alert("Request was unsuccessful: "+ xhr.status); }}catch (ex) {
      // Assume ontimeout}}}; xhr.open("get"."timeout.php".true);
xhr.timeout = 1000; // Set a 1-second timeout
xhr.ontimeout = function () {
  alert("Request did not return in a second.");
};
xhr.send(null);
Copy the code
  • The readyState will still change to 4 after the timeout and will also triggeronreadystatechangeEvent handler, access after timeoutstatusProperty error, so use try/catch statements.

The overrideMimeType() method

  • MIME type used to override the XHR response.
  • insend()Previous Settings.

2. Progress events

  • loadstart: Emitted when the first byte of the response is received
  • progress: Fires repeatedly during receiving a response
  • error: Triggered when a request error occurs
  • abort: in the callabort()Triggered when the connection is terminated
  • load: Triggered when the response is received successfully
  • loadend: Triggered after error, abort, and load when the communication is complete

1. Load events

  • To simplify the interaction pattern, no checking is requiredreadyStateattribute

2. Progress event

  • Trigger repeatedly during receiving data, receive when triggeredeventObject, whose properties
    • targetXHR object
    • lengthComputableBoolean value indicating whether progress information is available
    • positionNumber of bytes received
    • totalSizeThe total number of bytes defined by the content-Type header of the response

3. Cross-source resource sharing

  • The main limitation of Using XHR for Ajax communication is the cross-source security policy. By default, only resources that are in the same domain as the page that initiates the request can be accessed to prevent some malicious behavior. Cross-site Resource sharing (CORS) defines how browsers and servers can communicate across sources
  • The basic idea is to use custom HTTP headers to allow the browser and server to understand each other to determine whether a request or response should succeed or fail
  • Simple request, no custom header, request body type text/plain, with an extra header when sentOriginContains the source (protocol, domain name, port) of the page that sent the request so that the server can determine whether to provide it with a response. Such asOrigin: http://www.xxx.net
  • If the server decides to respond, it should send itAccess-Control-Allow-OriginHeader containing the same source or*, such asAccess-Control-Allow-Origin: http://www.xxx.net
  • Without this header, or with an active but mismatched source, the surface will not respond to browser requests. Neither the request nor the response contains cookie information.
  • XMLHttpRequest natively supports CORS, passing in absolute urls to access sources in different domains
  • Cross-domain XHR objects allow access to status and statusText attributes, allowing synchronization, but with additional restrictions
    • You can’t usesetRequestHeader()Set the custom header
    • Cannot send and receivecookie
    • getAllResponseHeaders()Method always returns an empty string

1. Pre-check request

  • CORS throughPreview the requestThe server authentication mechanism allows you to customize headers, methods other than GET and POST, and different request body content types. You need to send a request that contains the following header using the OPTION method
    • OriginSame as simple request
    • Access-Control-Request-MethodRequest the method you want to use
    • Access-Control-Request-Header(Optional) A comma-separated list of custom headers to use
  • The server can determine whether to allow this type of request and sends the following header message to the browser in response
    • Access-Control-Allow-OriginWith simple request lines
    • Access-Control-Allow-MethodAllowed methods (comma-separated list)
    • Access-Control-Allow-HeaderHeaders allowed by the server (comma-separated list)
    • Access-Control-Max-AgeNumber of seconds to cache precheck requests
  • After the precheck request is returned, the results are cached for a specified period of time.

2. Credential request

  • Cross-source requests do not provide credentials by defaultwithCredentialsProperty set to true indicates that the request sends credentials
  • If the server allows a credential request, it respondsAccess-Control-Allow-Credentials: true
  • If a credential request is sent and the server returns a response without this header, the browser does not pass the response to JavaScript, i.e. responseText is an empty string, status is 0, and onError () is called.
  • The server can also send this HTTP header in a response to a prechecked request, indicating that the source allows credential requests to be sent.

4. Alternative cross-source technologies

  • Cross-source dependencies used to be DOM features.

1. Image detection

  • using<img>Tags cross and communicate, and any page can cross and load images without worrying about restrictions. You can create images on the fly and know when a response is received through their onLoad and onError event handlers.
  • Often used for image detection, it is simple, cross-domain, one-way communication with the server. The data is sent as a query string, and the response can be set arbitrarily, typically a bitmap image or a status code with a value of 204. The browser doesn’t get any data from image detection, but it knows when to expect a response from events.
let img = new Image()
img.onload = img.onerror = function() {
  alert('Done! ')
}
img.src = "http://www.example.com/test?name=Nicholas"
Copy the code

2, the json

  • JSONP (JSON with Padding), a popular JSON variant of Web services.
  • The format is divided into two parts: callback and data
    • A callback is a function that should be invoked after the page receives a response, and usually the name of the callback function is dynamically specified by request
    • The data is the JSON data passed as arguments to the callback function.
  • http://freegeoip.net/json/?callback=handleResponse, usually specifying the callback function name as a string.
  • JSONP calls are created dynamically<script>Element and specifies the cross-domain URL implementation for the SRC attribute. At this time<script>with<img>Element, which can load resources from other domains without restriction.
function handleResponse(response) {
  console.log(response)
}
let script = document.createElement("script")
script.src = "http://fxxx/json/? callback=handleResponse"
document.body.insertBefore(script, document.body.firstChild)
Copy the code
  • The response can be accessed directly, enabling bidirectional communication between the browser and the server. Disadvantages:
    • Executable code is pulled from different domains, possibly adding malicious content to the response if the domain is not trusted.
    • It is difficult to determine whether a JSONP request failed, although HTML5 does<script>Element, but has not been implemented by any browser. You need to use a timer to decide whether to abandon waiting for a response.

5, Fetch the API

  • Performs all the tasks of an XMLHttpRequest object, is easier to use, has a more modern interface, and can be used in Web tools such as Web worker threads. It must be asynchronous.

1. Basic Usage

  • Under the global scope, including the home page thread, module, and worker thread.

1. Dispatch the request

  • Fetch () requires input, usually the URL of the resource to be fetched, and returns a date

  • When the request completes and the resource becomes available, the appointment is resolved as a Response object.

    fetch('bar.txt')
    	.then((response) = > {
        console.log(response)
      })
    // Response {type: "basic", url: ... }
    Copy the code

Read the response

  • The easiest way to read is to get content in plain text, the text() method. Return a term that will be resolved for obtaining the full content of the resource:

    fetch('bar.txt')
    	.then((response) = > {
        resonse.text().then((data) = > {
          console.log(data)
        })
      })
    
    fetch('bar.txt')
    	.then((response) = > response.text())
    	.then((data) = > console.log(data))
    Copy the code

3. Failed to process the status code and request

  • Supported byResponseThe status and statusText properties check the status of the response.
    • Request received successfully 200, requested non-existent resource 404, requested URL if the server throws error 500
  • It can be set explicitlyfetch()Behavior when a redirect is encountered. The default behavior is to follow the redirect and return a response with a status code other than 300 to 399redirectedProperty will be set to true and the status code will remain 200
  • When the request fails, the fetch() will be resolved whenever the server returns a response
  • Generally, a return of 200 is considered a success. You can check the Response object when the value is not 200 ~ 299okattribute
  • A real fetch() failure causes the date to be rejected because the browser timed out because the server did not respond
  • CORS violations, no network connection, HTTPS mismatches, and other browser/network policy issues can all result in a rejection.
  • The url property allows you to check the full URL used when sending a request through fetch()

4. Customize options

  • When using only urls, fetch() sends a GET request with minimal headers. The second parameter is set as follows:

  • body

    • Specifies the content of the request body when it is used
    • Must be an instance of Blob, BufferSource, FormData, URLSearchParams, ReadableStream, or String
  • cache

    • Used to control the browser’s interaction with the HTTP cache. To track cached redirects, the redirect property value of the request must be “follow”, must comply with the same-origin policy, and must be one of the following values
      • Default (default)
        • Fetch () returns the hit valid cache and does not send the request
        • A conditional request is sent when an invalid cache is hit. If the response changes, the cache value is updated, and fetch() returns the cached value,
        • A missed cache sends the request, caches the response, and fetch() returns the response
      • no-store
        • The browser sends the request without checking the cache
        • The response is not cached and is returned directly via fetch()
      • reload
        • The browser sends the request without checking the cache
        • The cache response is returned in fetch()
      • no-cache
        • A conditional request is sent whether a valid cache or an invalid cache is hit. If the response has changed, the cache value is updated, and fetch() returns the cached value,
        • A missed cache sends the request, caches the response, and fetch() returns the response
      • force-cache
        • Both valid and invalid caches hit are returned via fetch(), and no request is sent
        • A missed cache sends the request, caches the response, and fetch() returns the response
      • only-if-cached
        • Caching is only used if the request pattern is SAME-Origin
        • Both valid and invalid caches hit are returned via fetch(), and no request is sent
        • The cache returned a response with status code 504
  • credentilas

    • Specify how to include cookies in outgoing requests, similarwithCredentialsThe label
      • omit
        • Don’t send a cookie
      • Same-origin (default)
        • Cookies are only sent if the request URL is the same as the page that sent the fetch() request
      • include
        • Cookies are included in both same-origin and cross-domain applications
  • headers

    • Used to specify the request header
      • It must be an instance of a Headers object or a regular object that contains key/value pairs in string format
      • The default value is a Headers object that contains no key-value pairs, but the request sends an invisible default header.
  • integrity

    • Enforce child resource integrity
    • Must be a string containing a child resource integrity identifier
    • Default empty string
  • keepalive

    • Instructs the browser to allow requests to exist beyond the page declaration cycle. Suitable for reporting events or analysis.
    • Boolean value. Default is false
  • method

    • Specify the HTTP request method
      • GET the default
      • POST
      • PUT
      • PATCH
      • DELETE
      • HEAD
      • OPTIONS
      • CONNECT
      • TARCE
  • mode

    • Specifies the request pattern that determines whether the response from the cross-source request is valid and how many responses the client can read.
      • cors
        • Allows cross-source requests following the CORS protocol
        • The response is a CORS filtered response. That is, the accessible browser headers are whitelisted by the browser.
        • Default value for manually creating a Request instance
      • no-cors
        • Allow cross-source requests that do not need to send precheck requests (HEAD, GET, and ribbon have posts that satisfy the CORS request headers)
        • The response type is Opaque. That is, the response cannot be read
        • Default value for non-manual Request instance creation
      • same-origin
        • No cross-source requests are allowed to be sent
      • navigate
        • Used to support HTML navigation and only to navigate between documents
  • redirect

    • Used to specify how to redirect the response
    • The status code is 301, 302, 303, 307, or 308
      • Follow (default)
        • Trace the redirected request with the response of the final non-redirected URL as the final response
      • error
        • A redirect request throws an error
      • manual
        • Instead of tracking the redirection, a response of type OpaquerrDirect is returned
        • While still exposing the desired redirect URL
        • Allows manual tracing of redirects
  • referrer

    • Used to specify the content of the HTTP Referer header
      • no-referrer
        • Take no-referrer as the value
      • Client/About: Client (default)
        • Take the current URL or no-referrer (depending on the source policy referrerPolicy) as the value
      • <URL>
        • With the forged URL as the value, the source of the forged URL must match the source executing the script
  • referrerPolicy

    • The Referer header used to specify HTTP
      • no-referrer
        • The Referer header is not included in the request
      • No-referreer-when – retracted (default)
        • For requests sent from a secure HTTPS context to an HTTP URL, the Referer header is not included
        • For all other requests, set the Referer to the full URL
      • origin
        • For all requests, set the Referer to include the source
      • same-origin
        • For cross-source requests, the Referer header is not included
        • For same-origin requests, set the Referer to the full URL
      • strict-origin
        • For requests sent from a secure HTTPS context to an HTTP URL, the Referer header is not included
        • For all other requests, set the Referer to include only the source
      • origin-when-cross-origin
        • For cross-source requests, set the Referer to include only the source
        • For same-origin requests, set the Referer to the full URL
      • strict-origin-when-cross-origin
        • For requests sent from a secure HTTPS context to an HTTP URL, the Referer header is not included
        • For all other cross-source requests, set the Referer to include only the source
        • For same-origin requests, set the Referer to the full URL
      • unsafe-url
        • Set the Referer to the full URL for all requests
  • signal

    • Used to support AbortController to interrupt an ongoing FETCH () request
    • Must be an instance of AbortSignal
    • The default is an instance of AbortSignal for the associated controller

2. The common Fetch request pattern

1. Send JSON data

let payload = JSON.stringify({
  foo: 'bar'
});
let jsonHeaders = new Headers({
  'Content-Type': 'application/json'
});
fetch('/send-me-json', {
  method: 'POST'.// An HTTP method must be used when sending the request body
  body: payload,
  headers: jsonHeaders
})
Copy the code

2. Send parameters in the request body

  • The request body supports arbitrary string values through which request parameters can be sent
let payload = 'foo=bar&baz=qux';
let paramHeaders = new Headers({
	'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}); 
fetch('/send-me-params', {
	method: 'POST'.// An HTTP method must be used when sending the request body
	body: payload,
	headers: paramHeaders
});
Copy the code

3. Send files

  • The request body supports the FormData implementation, so fetch() can also serialize and send files of file fields
let imageFormData = new FormData();
let imageInput = document.querySelector("input[type='file']");
imageFormData.append('image', imageInput.files[0]);
fetch('/img-upload', {
  method: 'POST'.body: imageFormData
});

// This fetch() implementation can support multiple files:
let imageFormData = new FormData();
let imageInput = document.querySelector("input[type='file'][multiple]");
for (let i = 0; i < imageInput.files.length; ++i) {
  imageFormData.append('image', imageInput.files[i]);
}
fetch('/img-upload', {
  method: 'POST'.body: imageFormData
});
Copy the code

Load the Blob file

  • The Fetch API can provide bloB-type responses, and BLOBS are compatible with multiple browser apis.
  • A common practice is to explicitly load the image file into memory and then add it to the HTML image element.
  • You can use the BLOB method exposed by the response object. This method returns a term, resolved as an instance of a Blob. You can then pass this instance toURL.createObjectUrl()To generate values that can be added to the image element SRC attribute.
const imageElement = document.querySelector('img');
fetch('my-image.png')
  .then((response) = > response.blob())
  .then((blob) = > {
    imageElement.src = URL.createObjectURL(blob);
  });
Copy the code

5. Send cross-source requests

  • The response header must contain the CORS header to ensure that the browser receives the response
  • A no-CORS request can also be sent if the code does not require an access request. In this case, the type attribute of the response is Opaque. Therefore, the response cannot be read. This approach is suitable for sending probe requests or caching responses for later use.
fetch('//cross-origin.com', { method: 'no-cors' })
	.then((response) = > console.log(response.type));
// opaque
Copy the code

6. Interrupt request

  • Fetch the API support through AbortController/AbortSignal interrupt request.
  • Calling abortController.abort () interrupts all network traffic, especially when you want to stop a large load. Interrupting an ongoing FETCH () request results in a rejection that contains an error
let abortController = new AbortController();

fetch('wikipedia.zip', { signal: abortController.signal })
	.catch(() = > console.log('aborted! ');
         
// Interrupt the request after 10 milliseconds
setTimeout(() = > abortController.abort(), 10);
// It has been interrupted
Copy the code

3, Headers object

  • Containers for outgoing request and inbound response headers.

  • By the Request. The prototype. Headers

  • New Headers() creates a new instance

1. Similarities between Headers and Map

  • All have get(), set(), has(), delete(), and so on
  • Can be initialized with an iterable
  • All have the same keys(), values(), and entries() iterator interfaces

2. Headers unique feature

  • Can be initialized as key-value pairs
  • Support the use ofappend()Method adds multiple values. Calling a nonexistent header is equivalent to calling set(), and subsequent calls are concatenated with comma delimiters

3. Head guard

  • Not all HTTP headers can be modified by clients, and guards are used to prevent unwanted modifications. Different guard Settings change the set, Append, and DELETE behaviors. Violations of guard restrictions raise TypeError
  • Will show different behaviors due to different sources, its behavior is controlled by the guard.
The guard situation limit
none Activated when a Headers instance is created through the constructor There is no
request Activated when the Request object is initialized via the constructor and the mode value is non-no-cors The forbidden header is not allowed to be modified
request-no-cors Initializing the Request object via the constructor, and mode Non-simple headers are not allowed to be modified
response Activated when the Response object is initialized via the constructor The response header whose modification is prohibited is not allowed to be modified
immutable Activated when the Response object is initialized via the error() or redirect() static method No headers are allowed to be modified

4. Request object

  • The interface to retrieve a resource request exposes information about the request and different ways in which the request body can be used

Create a Request object

  • Constructor initialization

    let r = new Request('https://foo.com'); 
    Copy the code
  • Accept the second argument, no values involved in the init object will be used by default

    // Create the Request object with all the default values
    console.log(new Request(' '));
    
    // Request {
    // bodyUsed: false
    // cache: "default"
    // credentials: "same-origin"
    // destination: ""
    // headers: Headers {}
    // integrity: ""
    // keepalive: false
    // method: "GET"
    // mode: "cors"
    // redirect: "follow"
    // referrer: "about:client"
    // referrerPolicy: ""
    // signal: AbortSignal {aborted: false, onabort: null}
    // url: "
            
             "
            
    // }
    Copy the code
  • Created with the specified initial value

2. Clone the Request() object

  • Using constructors

    let r1 = new Request('https://foo.com');
    let r2 = new Request(r1);
    console.log(r2.url); // https://foo.com/ 
    Copy the code
    • Passing in an init object overwrites the value of the same name
    • The request for the first request will be marked as “bodyUsed”.
    • If the source object has a different source than the new object being created, the referrer attribute is cleared and same-Origin is returned if the source object is mode navigate
  • Clone () method

    • Create an identical copy, with no values overwritten and not marked as used
    let r1 = new Request('https://foo.com', { method: 'POST'.body: 'foobar' });
    let r2 = r1.clone();
    console.log(r1.url); // https://foo.com/
    console.log(r2.url); // https://foo.com/
    console.log(r1.bodyUsed); // false
    console.log(r2.bodyUsed); // false 
    Copy the code
    • Object whose bodyUsed property is true cannot create a copy of this object
    let r = new Request('https://foo.com');
    r.clone();
    new Request(r);
    // There are no errors
    r.text(); // Set bodyUsed to true
    r.clone();
    // TypeError: Failed to execute 'clone' on 'Request': Request body is already used
    new Request(r);
    // TypeError: Failed to construct 'Request': Cannot construct a Request with a
    Request object that has already been used. 
    Copy the code

Use the Request object in fetch()

  • When fetch() is called, you can pass in a Request instance that has already been created.
  • The init object passed to fetch() overwrites the value of the incoming request object
let r = new Request('https://foo.com');
// Send a GET request to foo.com
fetch(r);
// Send a POST request to foo.com
fetch(r, { method: 'POST' }); 
Copy the code
  • Fetch () internally clones the incoming Request object and cannot send a Request with an already used Request object
  • A Request from the Request body can only be used in one fetch
  • To be called multiple times, it needs to be called before the request is sentclone()
let r = new Request('https://foo.com',
 { method: 'POST'.body: 'foobar' });

// All three will succeed
fetch(r.clone());
fetch(r.clone());
fetch(r); 
Copy the code

5. Response object

  • The interface to get the resource response exposes information about the response and also exposes different ways of using the response body

Create a Response object

  • Constructor is created, and no arguments are required. The properties are default values.

    let r = new Response();
    console.log(r);
    // Response {
    // body: (...)
    // bodyUsed: false
    // headers: Headers {}
    // ok: true
    // redirected: false
    // status: 200
    // statusText: "OK"
    // type: "default"
    // url: ""
    // } 
    Copy the code
  • Accepts an optional body argument, which can be NULL. Equivalent to the body in the fetch() argument init.

  • You can also receive an optional init object

    • headers
      • Must be an instance of a Headers object or a regular object that contains string key/value pairs
      • Default is a Headers object with no key/value pairs
    • status
      • Status Indicates the integer of the HTTP response status code
      • The default value is 200
    • statusText
      • A string representing the status of the HTTP response
      • The default is an empty string
  • Generating a Response object is essentially a call to fetch(), which returns a contract that will eventually resolve into a Response object that represents the actual HTTP Response

  • The Response class also has two methods for generating a Response object

    • Response.redirect()
      • The former receives a URL and a redirection status code (301, 302, 303, 307, or 308)
      • Returns the redirected Response object
      • The provided status code must correspond to the redirect, or an error will be thrown
    • Response. error()
      • A Response object that generates a network error (a network error causes the FETCH () period to be rejected)

2. Read the response status information

  • The Response object contains a set of read-only properties that describe the state of the request after it completes
    • headers
      • The Headers object contained in the response
    • ok
      • A Boolean value that indicates the meaning of the HTTP status code. The value is true for 200 to 299 status codes, and false for other status codes
    • redirected
      • Boolean value indicating whether the response has been redirected at least once
    • status
      • An integer that represents the HTTP status code of the response
    • statusText
      • A character string containing a formal description of the HTTP status code.
      • This value is derived from the optional HTTP Reason-phrase field, so if the server rejects the response as reason-phrase, this field may be an empty string
    • type
      • String containing the response type.
      • Basic: represents a standard homologous response
      • Cors: Represents a standard cross-source response
      • Error: indicates that the Response object is created with Response.error()
      • Opaque: Indicates the cross-source response returned by fetch() of no-cors
      • Opaqueredirect: represents the response to a request with redirect set to manual
    • url
      • A string containing the response URL.
      • For the redirected response, this is the final URL, and the non-redirected response is generated by this

3. Clone the Response object

  • clone()

    • This method creates an identical copy

    • No values are overwritten. This does not mark the request body of any request as used

    • If the bodyUsed property of the response object is true (that is, the body of the response has been read), a copy of the object cannot be created. Cloning after the response body has been read causes TypeError to be thrown

    • A Response object with a Response body can be read only once. (A Response object that does not contain the Response body is not subject to this restriction.)

    • To read the same Response object containing the Response body multiple times, clone() must be called before the first read:

    • Pseudo-cloning can be performed by creating a Response instance with the original Response body.

      • The key is that this does not mark the first Response instance as read, but rather is shared between the two responses
    let r1 = new Response('foobar');
    let r2 = new Response(r1.body);
    
    console.log(r1.bodyUsed); // false
    console.log(r2.bodyUsed); // false
    
    r2.text().then(console.log); // foobar
    r1.text().then(console.log);
    // TypeError: Failed to execute 'text' on 'Response': body stream is locked
    Copy the code

6. Request, Response and Body are mixed in

  • Both Request and Response use the Body of the Fetch API mixed in to achieve payload capacity for both.
  • This blend provides a read-only body attribute (implemented as ReadableStream), a read-only bodyUsed Boolean value (indicating whether the body stream has been read), and a set of methods for reading content from the stream and converting the result to some JavaScript object type.
  • Reasons for use as a stream:
    • The size of the payload can cause network latency
    • The flow API itself has an advantage in handling payloads
  • It is best to obtain the resource body once
  • The appointment waits for the principal flow report to complete and the buffer to be resolved before resolution. This means that the client must wait for the resource of the response to load completely before accessing its content.

1, the Body. The text ()

  • Returns the date to resolve the UTF-8 string obtained for buffer dump
// The following code shows using body.text () on the Response object:
fetch('https://foo.com')
	.then((response) = > response.text())
	.then(console.log);
/ / 
      
// <head>
// 
      
// ...

// The following code shows using body.text () on the Request object:
let request = new Request('https://foo.com',
 { method: 'POST'.body: 'barbazqux' });
request.text()
	.then(console.log);
// barbazqux 
Copy the code

2, the Body. The json ()

  • Return date, resolve to dump the resulting JSON buffer
// The following code shows using body.json () on the Response object:
fetch('https://foo.com/foo.json')
	.then((response) = > response.json())
	.then(console.log);
// {"foo": "bar"}

// The following code shows using body.json () on the Request object:
let request = new Request('https://foo.com',
 { method:'POST'.body: JSON.stringify({ bar: 'baz'})}); request.json() .then(console.log);
// {bar: 'baz'} 
Copy the code

3, Body. FormData ()

  • The browser can serialize/deserialize a FormData object into a body
  • The body.formData () method returns a date that resolves to dump the resulting formData instance to the buffer
// The following code shows using body.formdata () on the Response object:
fetch('https://foo.com/form-data')
	.then((response) = > response.formData())
	.then((formData) = > console.log(formData.get('foo'));
// bar
        
// The following code shows using body.formdata () on the Request object:
let myFormData = new FormData();
myFormData.append('foo'.'bar');
let request = new Request('https://foo.com',
 { method:'POST'.body: myFormData });
request.formData()
	.then((formData) = > console.log(formData.get('foo'));
// bar 
Copy the code

4, the Body. ArrayBuffer ()

  • Returns a period to resolve the resulting ArrayBuffer instance to dump the buffer
// The following code shows using body.arrayBuffer () on a Response object:
fetch('https://foo.com')
	.then((response) = > response.arrayBuffer())
	.then(console.log);
// ArrayBuffer(...) {}

// The following code shows how to use body.arrayBuffer () on a Request object:
let request = new Request('https://foo.com',
 { method:'POST'.body: 'abcdefg' });

// Prints a binary encoded string as an integer
request.arrayBuffer()
	.then((buf) = > console.log(new Int8Array(buf)));
// Int8Array(7) [97, 98, 99, 100, 101, 102, 103]
Copy the code

5, the Body. A blob ()

  • Returns a date to resolve the resulting Blob instance for buffer dump
// The following code shows using body.blob () on the Response object:
fetch('https://foo.com')
	.then((response) = > response.blob())
	.then(console.log);
// Blob(...) {size:... , type: "..." }

// The following code shows using body.blob () on a Request object:
let request = new Request('https://foo.com',
 { method:'POST'.body: 'abcdefg' });
request.blob()
	.then(console.log);
// Blob(7) {size: 7, type: "text/plain; charset=utf-8"}
Copy the code

6. One-time flow

  • Body mixin is built on top of ReadableStream, so the Body stream can only be used once.

  • This means that all body mixin methods can only be called once and an error will be thrown when called again

  • As part of the Body blend, the bodyUsed Boolean property indicates whether ReadableStream has been ingested

7. Use ReadableStream body

  • From the TCP/IP point of view, the transmitted data arrives at the endpoint in chunks and is limited by the network speed.
  • The receiving endpoint allocates memory for this and writes the received block to memory.
  • The Fetch API supports reading and manipulating blocks in real time as they arrive through ReadableStream.
  • ReadableStream exposed thegetReader()Method, is used to produce ReadableStreamDefaultReader, the reader can be used for asynchronous data block in the data arrived. The format of the data stream is Uint8Array.
fetch('https://fetch.spec.whatwg.org/')
  .then((response) = > response.body)
  .then((body) = > {
    let reader = body.getReader();
    console.log(reader); // ReadableStreamDefaultReader {}
    reader.read()
      .then(console.log);
  });
// { value: Uint8Array{}, done: false }
Copy the code
  • You can recursively call the read() method after retrieving the entire payload as the data stream arrives
fetch('https://fetch.spec.whatwg.org/')
  .then((response) = > response.body)
  .then((body) = > {
    let reader = body.getReader();

    function processNextChunk({ value, done }) {
      if (done) {
        return;
      }
      console.log(value);
      return reader.read()
        .then(processNextChunk);
    }
    return reader.read()
      .then(processNextChunk);
  });
// { value: Uint8Array{}, done: false }
// { value: Uint8Array{}, done: false }
// { value: Uint8Array{}, done: false }
// ... 
Copy the code
  • Asynchronous functions are perfect for such fetch() operations. The recursive call above can be flattened by using async/await
fetch('https://fetch.spec.whatwg.org/')
  .then((response) = > response.body)
  .then(async function (body) {
    let reader = body.getReader();
    while (true) {
      let {
        value,
        done
      } = await reader.read();
      if (done) {
        break;
      }
      console.log(value); }});// { value: Uint8Array{}, done: false }
// { value: Uint8Array{}, done: false }
// { value: Uint8Array{}, done: false } 
// ...
Copy the code
  • The read() method can also be wrapped into the Iterable interface. This conversion can therefore be implemented conveniently in the for-await-of loop
fetch('https://fetch.spec.whatwg.org/')
	.then((response) = > response.body)
	.then(async function(body) {
  	let reader = body.getReader()
    
    let asyncIterable = {
      [Symbol.asyncIterator]() {
        return {
          next() {
            return reader.read()
          }
        }
      }
    }
    for await (chunk of asyncIterable) {
      console.log(chunk)
    }
})
// { value: Uint8Array{}, done: false }
// { value: Uint8Array{}, done: false }
// { value: Uint8Array{}, done: false } 
// ...
Copy the code
  • Further wrapping asynchronous logic into generator functions
async function* streamGenerator(stream) {
  const reader = stream.getReader()
  try {
    while(true) {
      const { value, done } = await reader.read()
      if(done) {
        break
      }
      yield value
    }
  } finally {
    reader.releaseLock()
  }
}

fetch('https://fetch.spec.whatwg.org/')
	.then((response) = > response.body)
	.then(async function(body) {
  	for await (chunk of streamGenerator(body)) {
      console.log(chunk)
    }
})
Copy the code
  • After reading the Uint8Array block, the browser marks it for garbage collection. This can save a lot of memory space in cases where large amounts of data need to be continuously examined in discrete memory
  • The size of the buffer, and whether the browser waits for the buffer to fill before pushing it into the stream, depends on the implementation of the JavaScript runtime
  • The block size may vary from browser to browser, depending on bandwidth and network latency
    • Unit8Array blocks of different sizes
    • A partially filled Unit8Array block
    • The interval between blocks arriving is uncertain
  • Unit8Array is converted to readable text and TextDecoder returns the converted value. By setting stream: true, you can keep the previous buffer in memory so that content spanning two blocks can be decoded correctly
let decoder = new TextDecoder();
async function* streamGenerator(stream) {
  const reader = stream.getReader();
  try {
    while (true) {
      const {
        value,
        done
      } = await reader.read();
      if (done) {
        break;
      }
      yieldvalue; }}finally {
    reader.releaseLock();
  }
}
fetch('https://fetch.spec.whatwg.org/')
  .then((response) = > response.body)
  .then(async function (body) {
    for await (chunk of streamGenerator(body)) {
      console.log(decoder.decode(chunk, {
        stream: true})); }});Copy the code
  • Because you can create a Response object using ReadableStream, you can pipe it into another stream after reading the stream.
  • Then use the Body method on the new stream, such as text(). This allows you to examine and manipulate the flow content in real time as it arrives
fetch('https://fetch.spec.whatwg.org/')
  .then((response) = > response.body)
  .then((body) = > {
    const reader = body.getReader();
    // Create a second stream
    return new ReadableStream({
      async start(controller) {
        try {
          while (true) {
            const {
              value,
              done
            } = await reader.read();
            if (done) {
              break;
            }
            // Push the block of the main stream to the second streamcontroller.enqueue(value); }}finally {
          controller.close();
          reader.releaseLock();
        }
      }
    })
  })
  .then((secondaryStream) = > new Response(secondaryStream))
  .then(response= > response.text())
  .then(console.log);
Copy the code

6, Beacon API

  • Resolve that the UNLOAD event cannot send asynchronous requests during page destruction.
  • navigator.sendBeacon()Receive a URL a payload parameter of data and send a POST request.
  • Optional data payload parameters are ArrayBufferView, Blob, DOMString, FormData instance.
  • This method returns true if the request successfully entered the final task to be sent, false otherwise.
// Send a POST request
// URL: 'https://example.com/analytics-reporting-url'
// Request load: '{foo: "bar"}'

navigator.sendBeacon('https://example.com/analytics-reporting-url'.'{foo: "bar"}'); 
Copy the code
  • SendBeacon () is available at any time
  • After sendBeacon(), the browser adds the request to an internal request queue. The browser will actively send the request in the queue.
  • The browser guarantees that the request will be sent even if the original page is closed
  • Failures due to status codes, timeouts, and other network causes are completely opaque and cannot be handled programmatically
  • The beacon request carries all the cookies associated with calling sendBeacon()

7, Web sockets

  • The goal is full duplex, bidirectional communication with the server over a long – time connection
  • When a Web Socket is created in JavaScript, an HTTP request is sent to the server to initiate the connection.
  • When the server responds, the connection switches from the HTTP protocol to the Web Socket protocol using the Upgrade header of HTTP.
  • This means that Web sockets cannot be implemented through a standard HTTP server, but must use a proprietary server that supports the protocol.
  • Use ws:// and WSS ://. The former is an insecure connection, while the latter is a secure connection.
  • Very little data can be sent between the client and server without any burden on HTTP.

1, API

  • Creation must be passed in absolute URLS
  • The same origin policy does not apply to Web sockets, so you can open connections to arbitrary sites. Whether or not to communicate with pages from a particular source is entirely up to the server
let socket = new WebSocket("ws://www.example.com/server.php"); 
Copy the code
  • The browser creates the connection immediately after initializing the WebSocket object. Like XHR, WebSocket has a readyState property to indicate the current state.
    • Websocket.opening (0) : The connection is being established.
    • Websocket.open (1) : the connection has been established.
    • Websocket.closing (2) : The connection is CLOSING.
    • Websocket.close (3) : The connection is closed.
  • You can call the close() method to close the Web Socket connection at any time,
socket.close()
Copy the code
  • After calling close(), readyState immediately changes to 2 (the connection is closing) and to 3 (the connection is closed).

2. Send and receive data

  • To send and receive data through the connection, to send data to the server, usingsend()Method passes in a string, ArrayBuffer, or Blob
let socket = new WebSocket("ws://www.example.com/server.php");
let stringData = "Hello world!";
let arrayBufferData = Uint8Array.from(['f'.'o'.'o']);
let blobData = new Blob(['f'.'o'.'o']);

socket.send(stringData);
socket.send(arrayBufferData.buffer);
socket.send(blobData); 
Copy the code
  • The WebSocket object fires when the server sends a message to the clientmessageEvents.
  • This message event is similar to other message protocols and can be passedevent.dataProperty to the payload
socket.onmessage = function(event) {
	let data = event.data;
	// Perform some operations on the data
}; 
Copy the code
  • event.dataThe returned data could also be an ArrayBuffer or Blob. This is done by the WebSocket objectbinaryTypeProperty, which could be “blob” or “arrayBuffer”

3. Other events

  • Open: Triggered when a connection is successfully established.
  • Error: Triggered when an error occurs. The connection could not survive.
  • Close: Triggered when the connection is closed.
let socket = new WebSocket("ws://www.example.com/server.php");
socket.onopen = function () {
  alert("Connection established.");
};
socket.onerror = function () {
  alert("Connection error.");
};
socket.onclose = function () {
  alert("Connection closed.");
};
Copy the code
  • Only the event object for the close event has additional information. There are three additional properties on this object
    • WasClean Boolean value that indicates whether the connection is cleanly closed
    • Code Indicates the numeric status code from the server
    • Reason contains the message sent by the server
socket.onclose = function (event) {
  console.log(`as clean? ${event.wasClean} Code=${event.code} Reason=${event.reason}`);
};
Copy the code

8, security,

  • Any URL that Ajax can access can also be accessed through a browser or server
  • When an unauthorized system can access a resource, it can be considered a cross-site request forgery (CSRF) attack
  • The unauthorized system masquerades itself as requested by the server processing the request.
  • Ajax applications, large and small, can be affected by CSRF attacks, including harmless vulnerability verification attacks and malicious data theft or data destruction attacks
  • measures
    • Require SSL access to resources that can be accessed by Ajax
    • Require each request to send a token calculated according to the convention algorithm.
  • Note that the following measures are not effective against CSRF attacks
    • Ask for POST instead of GET requests (easily modify the request method)
    • Authenticate sources with source urls (source urls are easy to forge)
    • Cookie-based authentication (also easy to forge)