Front-end request development history Ajax, jQuery Ajax, fetch, axios (use + comparison + pit avoidance guide)

15481021:

Introduction

If you are ambiguous about the request, or know which request libraries are available, but you are only proficient in one or two of them, you don’t know all of them. Come on, this article is very suitable for you.

This article explains a change in the request library in the history of front-end development, from the beginning Ajax, to the later jQuery Ajax, and then fetch, and then axios. The author will introduce the use of each request library in detail, as well as the pitfalls. Finally, their respective advantages and disadvantages are summarized. I believe that after reading this article, you will gain something. Friends are also welcome to like and collect, I believe you will use it later.

The request interface of all the examples in this article is at the end of the article, using node + express to build

Before talking about the request library, let's recall the form first.

form

In most cases, the data or pictures or multimedia effects displayed on the webpage are static data, but sometimes the user needs to perform dynamic data interaction with the server through the webpage, such as login, registration and other operations, and a form is needed at this time.

The form is actually composed of elements such as input boxes, radios, check boxes, etc. When the user clicks the submit button, the browser will send the data to the URL set in the form. After the server corresponding to the URL receives and processes the data, it will send the data to returned to the browser.

form submission

There are generally two ways to submit a form:

The first is to use typethe submitbutton for submit.

The second is to get the form and then manually call submit()the method to submit it.

submit button to submit

<h3>form1 直接提交</h3>
<form action="http://localhost:3000/test" onsubmit="submit1()">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <input type="submit" />
</form>

The page is rendered as follows, click type="submit"the submit button to submit our form. After submission, the method corresponding to our onsubmitattribute will be automatically triggered, here is submit1the method that will be triggered.

image.png

Manually call the submit method to submit

<h3>form2 手动提交</h3>
<form action="http://localhost:3000/test" id="form2" onsubmit="submit1()">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <!-- 这个按钮可以放在表单内也可以放在表单外 -->
  <input type="button" id="submitBtn2" value="提交" onclick="handleSubmit()"/>
</form>

In jsit, we can also get the form in the event of the button, and then call submit()the method of the form to submit the form.

handleSubmit = function () {
    
    
  const form2 = document.getElementById("form2");
  form2.submit();
};

The page rendering is as follows, click the submit button, and then manually submit()submit our form through the method. Note that this method will not trigger onsubmitthe method corresponding to the attribute.

image.png

Here we are buttondirectly binding the click event, of course, you can also process it by obtaining buttonand binding the event.button

// 方式1
const submitBtn2 = document.getElementById("submitBtn2");
submitBtn2.onclick = function () {
    
    
  const form2 = document.getElementById("form2");
  form2.submit();
};

// 方式2
const submitBtn2 = document.getElementById("submitBtn2");
submitBtn2.addEventListener("click", function () {
    
    
  const form2 = document.getElementById("form2");
  form2.submit();
});

Because the page is refreshed every time the form is submitted , the experience is not very good, so it came out later Ajax. AjaxIt is a technology that can update some web pages without reloading the entire web page. In order to make the request smoothly later Ajax, we must prevent the behavior of page jump by default after the form is submitted. So let's take a look at the ways to prevent form submissions?

prevent form submission

There are generally three ways to prevent form submission:

The first is onsubmitto return to the bound method falseto prevent form submission.

The second is to return the submit button falseto prevent form submission.

The third is to block the default behavior of the submit button to prevent form submission.

onsubmit returns false

Let's look at the first

<form action="http://localhost:3000/test" onsubmit="return submit1()">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <input type="submit" id="submitBtn1" />
</form>

Returning in onsubmitthe corresponding method falsecan prevent the form submission

function submit1() {
    
    
  return false;
}

Submit button returns false

<form action="http://localhost:3000/test">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <input type="submit" id="submitBtn2" onclick="return handleSubmit()" />
</form>

falseJust return in the method corresponding to the submit button . Similar to the above.

function handleSubmit() {
    
    
  return false;
}

Of course, you can also use the method of binding events

<form action="http://localhost:3000/test">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <input type="submit" id="submitBtn2" />
</form>

falseYou can also prevent the form from submitting by binding an event to the submit button and returning in the event . Note that it is invalidaddEventListener to return in this way of binding events .false

const submitBtn2 = document.getElementById("submitBtn2");
submitBtn2.onclick = function () {
    
    
  return false;
};

// 无效 无 效无效 无效
const submitBtn2 = document.getElementById("submitBtn2");
submitBtn2.addEventListener("click", function () {
    
    
  return false;
});

prevent submit button default behavior

We can also block the default event of the submit button to prevent form submission.

<form action="http://localhost:3000/test">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <input type="submit" id="submitBtn2" onclick="handleSubmit()" />
</form>

preventDefaultUse the blocking default event in the method corresponding to the submit button .

// 这种方式需要window.event来获取事件对象
function handleSubmit(e) {
    
    
  const event = e || window.event;
  event.preventDefault();
}

Of course, you can also use the method of binding events

<form action="http://localhost:3000/test">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <input type="submit" id="submitBtn2" />
</form>

preventDefaultBy binding the event to the submit button, and then using the blocking default event in the event .

// 方式1
const submitBtn2 = document.getElementById("submitBtn2");
submitBtn2.onclick = function (e) {
    
    
  e.preventDefault();
};

// 方式2
const submitBtn2 = document.getElementById("submitBtn2");
submitBtn2.addEventListener("click", function (e) {
    
    
  e.preventDefault();
});

After talking about the submission of the form, let's talk about another very important knowledge point of the formenctype

enctype attribute

enctypeIt is used to define how to encode the data when the form data is submitted to the server. The optional values ​​are:

  1. application/x-www-form-urlencoded;
  2. multipart/form-data;
  3. text/plain

application/x-www-form-urlencoded

The default method is the first one application/x-www-form-urlencoded. When submitting data using the form form, it will be converted into key=value&key=valuedata in this format by default.

For the request, such a link getwill be generated from the form parameters , and the request will be made after the current link. For the request, the form parameters will be generated into such a link, and placed in the request body for the request.?key=value&key=valueactionpostkey=value&key=value

And some characters (Chinese, special characters, etc.) in the parameters will be encoded.

Why edit the submitted data?

When using the form form to submit data, the data needs to be encoded, because the data of the URL is transmitted to the server ?key=value&key=value&through , which has some special characters as functional properties. For example & ? =, if the data contains these characters and is not encoded , which may cause errors in the transmitted data. For example, ?key=valueif the value 123&456is originally, then the value received by the server becomes 123, and there is one more key=456. This encoding method is called URL percent encoding, and its standard includes In RFC3986.

multipart/form-data

When set multipart/form-datato , the browser does not encode characters, which is usually suitable for uploading files .

For multipart/form-datarequest data in the format, the data will be segmented by special tags, and then passed in the request body.

text/plain

text/plainWhen using the third method , the browser puts the request parameter bodyinto a string and processes it. This method is used to transmit the original HTTP message and does not apply any formatting processing.

Ajax

Next, let's take a look at Ajax that changed history . Because the page is refreshed every time the form is submitted , the experience is not very good. AjaxIt is a technology that can update some web pages without reloading the entire web page. So Ajaxthe appearance undoubtedly changed history. The user experience is greatly improved.

The native we are talking about here Ajaxmainly introduces the XmlHttpRequestuse of XmlHttpRequestobjects to send asynchronous requests to the server and obtain data from the server.

basic process

Let's first take a look at the steps required to send the simplest one Ajax.

create request object

First, you need to create a request object, and you need to consider browser compatibility when creating it.

let xhr;
if (window.XMLHttpRequest) {
    
    
  //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
  xhr = new XMLHttpRequest();
} else {
    
    
  // IE6, IE5 浏览器执行代码
  xhr = new ActiveXObject("Microsoft.XMLHTTP");
}

listen request

Before sending a request, we'd better listen to the request first, and readystatechangethe event will be executed at each stage of the request.

image.png

Generally, we only need to pay attention to the state of 4.

// 设置状态监听函数
xhr.onreadystatechange = function () {
    
    
  // 4成功
  if (this.readyState !== 4) return;

  // xhr对象,在这里获取响应结果
  console.log(this);
};

When a XMLHttpRequestrequest is abort()canceled by the method, its corresponding readystatechangeevent will not be fired.

initialization request

The XMLHttpRequest.open(method, url, async) method initializes a newly created request, or re-initializes a request.

  • method: the type of request; GET or POST
  • url: request address
  • async: true (asynchronous) or false (synchronous), the default is true
xhr.open(
  "get",
  `http://localhost:3000/testGet?name=randy&age=27` // 接口在文章末尾,使用node + express搭建
);

Set the return value type

After creating the request, we also need to set the type of response data, if not set, the default value will be used text.

Commonly used return value formats are as follows

  1. "" is the same as text
  2. text
  3. json
  4. blob
  5. document
  6. arraybuffer

Here we respond to yes json, so we need to set to josn.

xhr.responseType = "json";

send request

XMLHttpRequest.send()method for sending HTTP requests. If it is an asynchronous request (the default is asynchronous request), this method will return immediately after the request is sent; if it is a synchronous request, this method will not return until the response arrives (that is, it will prevent subsequent code execution).

XMLHttpRequest.send()The method accepts an optional parameter, which is the request body; if the request method is GET or HEAD, the request body should be set to null.

Here because we are getrequesting, we can just send a null.

xhr.send(null)

send()The data formats supported by the method are as follows, which postwill be used when requesting.

XMLHttpRequest.send();
XMLHttpRequest.send(String); // 传递js对象需要转成json字符串
XMLHttpRequest.send(URLSearchParams data);
XMLHttpRequest.send(FormData data);
XMLHttpRequest.send(ArrayBuffer data);
XMLHttpRequest.send(ArrayBufferView data);
XMLHttpRequest.send(Blob data);
XMLHttpRequest.send(Document data);
XMLHttpRequest.send(DOMString? data);

These request data formats need to be well known, otherwise passing unsupported data formats will cause request errors!

Get the response result

The response is actually in our onreadystatechangelistening event, let's take a look at what the successful xhrobject looks like.

image.png

Here we focus on response、status、statusText、readyStatethese values.

responseproperty returns the body of the response. The returned type is one of ArrayBuffer, Blob, Document, or string. JavaScript ObjectThis depends on the requested responseTypeattribute . If not specified, the result defaults to texttype.

statusis the http status code.

statusTextIs the http status information.

readyStateis the state of the current request object.

in-depth

We gave an example of the simplest getrequest earlier, let's take a closer look below. Such as post request, asynchronous, cancel request, error handling, etc.

send post request

The parameters of postthe request need to be placed send()in the method, and multiple data formats are supported. Below, the author uses the three most frequently used data formats to explain.

Let's create a form first, here we no longer use the form to submit data, but use the Ajax. So this form is just for us to get the data entered by the user. (Of course you can also not use the form).

<h3>form1</h3>
<form id="form1">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <input type="button" id="submitBtn1" onclick="request1()" value="提交" />
</form>

<h3>结果</h3>
<div id="result"></div>

We then request1create an xhrobject in the request method, initialize the request and monitor the request.

function request1() {
    
    
  // 创建xhr
  let xhr;
  if (window.XMLHttpRequest) {
    
    
    //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
    xhr = new XMLHttpRequest();
  } else {
    
    
    // IE6, IE5 浏览器执行代码
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
  }

  // 设置状态监听函数
  xhr.onreadystatechange = function () {
    
    
    // 4成功
    if (this.readyState !== 4) return;

    // xhr对象
    console.log(this);
    // 将响应结果放到div显示
    const resultDiv = document.getElementById("result");
    resultDiv.innerText = this.response;
  };

  // 初始化请求
  xhr.open("post", `http://localhost:3000/testPost`);
}

The default data format of the request body is text/plainthat we do not commonly use this kind of data in development, and generally use the following three data formats, so how to modify the data format we request? Then we have to use setRequestHeaderthe method, which is to set our request header.

The request data format is application/x-www-form-urlencoded

// 设置我们请求数据的格式
// 对于 发送数据方式2,这个设置请求数据可以免去,因为它会自动设置
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");

// 获取表单数据
const formData = new FormData(document.getElementById("form1"));
const name = formData.get("name");
const age = formData.get("age");

// 发送数据1
xhr.send(`name=${
      
      name}&age=${
      
      age}`);

// 发送数据方式2 直接借助 URLSearchParams 免去手动拼接参数
// const urlSearchParams = new URLSearchParams(formData);
// xhr.send(urlSearchParams);

Let's take a look at postthe effect of the request, and the result is returned successfully.

89edd7ad-cfca-4a5c-a4b3-a4759d85d550.gif

The request data format is application/josn

// 设置请求数据类型
xhr.setRequestHeader("Content-type","application/json");

// 获取表单数据
const formData = new FormData(document.getElementById("form1"));
const name = formData.get("name");
const age = formData.get("age");

// 发送json数据 需要转成字符串
xhr.send(JSON.stringify({
    
     name, age }));

Let's take a look at postthe effect of the request, and the result is returned successfully.

02b616d8-b509-4542-8d4f-5336669dd8ff.gif

The request data format is multipart/form-data

We generally use this data format to upload files, and it is not directly used to submit simple form data.

// 可以不设置 因为new FormData会自动将请求头设置为这种格式
xhr.setRequestHeader("Content-type","multipart/form-data");

// 获取表单数据
const formData = new FormData(document.getElementById("form1"));

// 初始化请求 使用第二个接口 使用multer特殊处理
xhr.open("post", `http://localhost:3000/testPost2`);

// 发送json数据 需要转成字符串
xhr.send(formData);

Let's take a look at postthe effect of the request, and the result is returned successfully.

02b616d8-b509-4542-8d4f-5336669dd8ff.gif

asynchronous

AjaxThe default is asynchronous. When openthe third parameter of our method is set to false, our request will be set to synchronous. Many friends think that synchronization means that the response result is sendthe return value of the method, but it is not. The synchronous and asynchronous here just means blocking and not blocking the running of subsequent codes. The response results need to be readystatechangeobtained in the listening event.

Let's look at two examples

First look at asynchronous

xhr.open(
  "get",
  `http://localhost:3000/testGet?name=${
      
      name}&age=${
      
      age}`,
  true
);

const result = xhr.send(null);
console.log(result);
console.log("后续代码");

Let's take a look at the output. An asynchronous request will not block subsequent code execution after the request, and sendthe method will not return a result.

image.png

Let's look at synchronization again

xhr.open(
  "get",
  `http://localhost:3000/testGet?name=${
      
      name}&age=${
      
      age}`,
  false
);

// 阻塞后续代码运行
const result = xhr.send(null);
console.log(result);
console.log("后续代码");

Let's take a look at the output. The synchronous request will block the execution of the subsequent code. The subsequent code will not run until the request has a result, and the sendmethod will not return the result.

image.png

cancel request

If the request has already been issued, the XMLHttpRequest.abort() method will terminate the request. When a request is terminated, its readyStateis set to 0, and the request's statusis set to 0.

xhr.abort();

image.png

error handling

The event is fired when a request encounters an error error. However, it should be noted that errors returned by the backend will not trigger onerrorevents, such as those returned by the backend 500 400. The event will only be triggered when the network is interrupted or cross-domain onerror.

// 设置请求失败时的监听函数
// 当网络中断或者跨域时会触发onerror事件
xhr.onerror = function () {
    
    
  console.error(this);
};

AjaxSummary

  1. The entire request process is quite cumbersome from creating, monitoring, initializing the request, and sending the request, and the efficiency of development and use is definitely not high.
  2. The request method is relatively limited, only get and post requests are supported
  3. Promise is not supported, and the request result needs to be obtained through the monitoring function, and it is easy to nest for requests with dependencies .
  4. The data format transmitted by the request is relatively limited, and does not support the current mainstream native js objects (need to be converted into json strings).
  5. You need to manually set the response return value type, otherwise text type data will be returned by default
  6. Support Cancellation Request

jQuery Ajax

jQuery AjaxAjaxIt is not a new thing, but an encapsulation of the original , making it easier to use and faster to develop.

$.ajax()

Before using ajaxto send a request, you need to go through a series of steps such as creating, monitoring, initializing the request, and sending the request, which is very troublesome. In jQuery, one method can get it done.

Let's look at an example.

First import the pagejQuery

<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>

Then create a form.

<h3>form1</h3>
<form id="form1">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <input type="button" id="submitBtn1" onclick="request2()" value="提交" />
</form>
<h3>结果</h3>
<div id="result"></div>

When the submit button is clicked, we send a getrequest to the backend server.

function request2() {
    
    
  $.ajax({
    
    
    url: "http://localhost:3000/testGet", // 规定发送请求的 URL。默认是当前页面。
    data: $("#form1").serialize(), // 规定要发送到服务器的数据。
    success(result) {
    
    
      console.log(result);
      $("#result").text(JSON.stringify(result));
    },
  });
}

Let's see the effect. The data is normally fetched and returned

image.png

Let's take postthe request as an example to explain $.ajax()the method in detail.

function request2() {
    
    
  const formData = new FormData(document.getElementById("form1"));
  const name = formData.get("name");
  const age = formData.get("age");

  $.ajax({
    
    
    type: "POST", // 规定请求的类型(GET 或 POST) 默认GET
    url: "http://localhost:3000/testPost2", // 规定发送请求的 URL。默认是当前页面。
    // data: formData, // 上传文件需要用到,传送formData会自动设置contentType: "multipart/form-data",我们需要设置contentType: false、processData: false
    // data: urlSearchParams, // 直接传递 URLSearchParams 对象 我们需要设置processData: false
    data: `name=${
      
      name}&age=${
      
      age}`, // 规定要发送到服务器的数据。支持这种search字符串类型。可以使用$("#form1").serialize()直接序列化出来
    // data: $("#form1").serialize(), // 把表单序列化成search字符串
    // data: $.param({ name, age }), // 把对象序列化成search字符串
    // data: { name, age }, // 支持对象类型
    // data: JSON.stringify({ name, age }), // 支持对象字符串类型。使用这种方式需要设置 contentType: "application/json"
    // contentType: "application/x-www-form-urlencoded", // 发送数据到服务器时所使用的内容类型。默认是:"application/x-www-form-urlencoded"。
    // contentType: "application/json", // 发送数据到服务器时所使用的内容类型。默认是:"application/x-www-form-urlencoded"。
    // contentType: false, // 不设置,当data是FormData是需要设置。
    dataType: "", // 预期的服务器响应的数据类型。如果不指定,jQuery 将自动根据 HTTP 包 MIME 信息来智能判断。可以设置json、text、xml、html等
    // processData: false, // 布尔值,规定通过请求发送的数据是否转换为查询字符串。默认是 true。
    beforeSend(xhr) {
    
    
      // 发送请求前运行的函数
      console.log(xhr);
    },
    success(result) {
    
    
      // 请求成功运行的函数
      console.log(result);
      $("#result").text(JSON.stringify(result));
    },
    error(xhr, status, error) {
    
    
      // 如果请求失败要运行的函数
      // 后端返回错误码也会进入该方法 比如 400/401/500
      console.log(error);
    },
    complete(xhr, status) {
    
    
      // 请求完成时运行的函数,不管成功或者失败
      console.log(status);
    },
  });
}

Here we focus on data, contentType, processData.

dataOnly supports URLSearchParams, FormData, name=${name}&age=${age}this search string, object, object string five forms. And need and contentTypecorresponding.

At that time, only the form of object string can becontentType: "application/json" passed .data

contentType: "application/x-www-form-urlencoded"At that time, datait can be a search string or an object, because the object will be automatically converted into a search character.

We can manually spell out the search string, and of course there is a more convenient method, which is $.serialize()和$.param()the method of use.

data: $("#form1").serialize() // 表单序列化
data: $.param({
    
     name, age }) // 对象序列化

When the parameter we pass datais URLSearchParamsthe format, it needs to be processDataset to falseturn off automatic conversion. Otherwise, an error will be reported.

When the parameter we pass datais FormDataa format (usually when uploading a file), it needs to be processDataset to falseturn off automatic conversion. and also needs to be contentTypeset to false. Otherwise, an error will be reported.

Of course, if you think the above $.ajax()method is too troublesome, we can also use the convenient methods corresponding to the request $.get(), $.post(), $.getJSON().

$.get()

$.get(URL,data,function(data,status,xhr),dataType)method loads data from the server using an HTTP GET request. It has four parameters.

  1. URL is required. Specifies the URL you need to request.

  2. data is optional. Specifies the data sent to the server with the request. Only query string and object types are supported .

  3. function is optional. Specifies a function to run when the request succeeds.

  4. dataType is optional. Specifies the expected data type of the server response. By default, jQuery will intelligently judge

Here we simply try

$.get(
  "http://localhost:3000/testGet",
  $("#form1").serialize(),
  function success(data, status, xhr) {
    
    
    console.log(data);
    $("#result").text(JSON.stringify(data));
  },
  "json"
);

can get the result correctly

image.png

$.post()

$.post(URL,data,function(data,status,xhr),dataType)method loads data from the server using an HTTP POST request. It has four parameters.

  1. URL is required. Specifies the URL you need to request.

  2. data is optional. Specifies the data sent to the server with the request. Only query string and object types are supported .

  3. function is optional. Specifies a function to run when the request succeeds.

  4. dataType is optional. Specifies the expected data type of the server response. By default, jQuery will intelligently judge

Here we simply try

$.post(
  "http://localhost:3000/testPost",
  $("#form1").serialize(),
  function success(data, status, xhr) {
    
    
    console.log(data);
    $("#result").text(JSON.stringify(data));
  },
  "json"
);

can get the result correctly

image.png

$.getJSON()

$.getJSON(url,data,function(data,status,xhr))The method fetches JSON data using an AJAX HTTP GET request. It has three parameters.

  1. URL is required. Specifies the URL you need to request.

  2. data is optional. Specifies the data sent to the server with the request. Only query string and object types are supported .

  3. function is optional. Specifies a function to run when the request succeeds.

Here we simply try

$.getJSON(
  "http://localhost:3000/testGet",
  $("#form1").serialize(),
  function success(data, status, xhr) {
    
    
    console.log(data);
    $("#result").text(JSON.stringify(data));
  }
);

can get the result correctly

image.png

It can be found that although the convenience method is more convenient to use, there are still many restrictions, especially the data transfer format, which only supports two types of query strings and objects . And there is no callback function for request errors, only successful callback functions.

jQuery AjaxSummary

  1. Compared with native Ajax, it encapsulates a series of methods, which is much more convenient to use.
  2. Compared with native Ajax, the request data format has been improved and native js objects are supported. It will automatically convert the native object into a search string and pass it on.
  3. Promise is not supported, the request result needs to be obtained through a callback function, and nesting is easy to occur for requests with dependencies.
  4. It is not mandatory to manually set the response return value type, jQuery Ajaxit will be automatically set according to the return result.
  5. Does not seem to support cancel requests

fetch

fetch(url, config)method is used to initiate a request to obtain a resource. It returns a promise, which promisewill be resolvepassed back to Responsethe object after the request is responded to.

fetch()It is not a native Ajaxencapsulation, but a request library natively supported by browsers.

Let's look at a simple example

fetch(`http://localhost:3000/testGet?name=randy&age=27`, {
    
    })
  .then((response) => {
    
    
    console.log(response);
    return response.json();
  })
  .then((res) => {
    
    
    console.log(res);
  });

output responseandres

image.png

It can be found that fetch()after the request is completed, the result is not returned directly, but a Response object . It corresponds to the server's HTTP response. We will focus on this object later. responseis an Streamobject , we need to call some of its methods to get the data we want. For example, we called it above response.json(). The function of this method is to convert the data into jsonformatted data.

response object

ok

Response.okThe attribute returns a Boolean value indicating whether the request is successful, truecorresponding to the status codes 200 to 299 of the HTTP request, and falsecorresponding to other status codes.

status

Response.statusThe property returns a number representing the status code of the HTTP response (eg 200 for a successful request).

statusText

Response.statusTextThe property returns a string indicating the status information of the HTTP response (for example, the server returned "OK" after the request was successful).

url

Response.urlproperty returns the requested URL. If there is a jump in the URL, this property returns the final URL.

type

Response.typeProperty returns the requested type. Possible values ​​are as follows:

  • basic: Ordinary requests, that is, same-origin requests.
  • cors: Cross-origin request.
  • error: Network errors, mainly for Service Workers.
  • opaque: If the fetch()requested typeattribute is set to no-cors, this value will be returned.
  • opaqueredirect: If the fetch()requested redirectattribute is set to manual, this value will be returned.

redirected

Response.redirectedThe property returns a boolean indicating whether the request has been redirected.

headers

ResponseThe object also has a Response.headersproperty that points to a Headers object , corresponding to all the headers of the HTTP response.

HeadersThe object provides the following methods for manipulating headers.

  • Headers.get(): According to the specified key name, return the key value.
  • Headers.has(): Returns a boolean indicating whether a header is included.
  • Headers.set(): Set the specified key name as a new key value, if the key name does not exist, it will be added.
  • Headers.append(): Add headers.
  • Headers.delete(): Remove header.
  • Headers.keys(): Returns a traverser that can traverse all key names in turn.
  • Headers.values(): Returns a traverser that can traverse all key values ​​in turn.
  • Headers.entries(): Returns a traverser that can traverse all key-value pairs ( [key, value]) in sequence.
  • Headers.forEach(): The headers are traversed in turn, and the parameter function will be executed once for each header.

For example, to get the responseContent-Type

response.headers.get('Content-Type'); // application/json; charset=utf-8

method of reading content

As we said earlier, the response content is response.bodyabove, but bodyit is an ReadableStreamobject, and we need further conversion to get the value we want.

What are the methods of conversion? We can call different read methods according to different types of data returned by the server.

  • response.text(): get the text string.
  • response.json(): get JSON object.
  • response.blob(): Get a binary Blob object.
  • response.formData(): Get FormData form object.
  • response.arrayBuffer(): Get a binary ArrayBuffer object.

config parameter

fetch(url, config)There are two parameters, urlwhich are the request address, so I won’t say more about this, let’s focus on it config.

Here I will introduce several important configparameters.

method

method: HTTP request method, GET, POST, DELETE, PUTare all set in this property.

headers

headers: An object used to customize HTTP headers. Such as commonly used content-type.

body

body: The data body of the POST request. Get and Head requests cannot set this parameter .

Let's take a look at which request data types fetch supports? Let's look at an example of the author's test.

fetch(`http://localhost:3000/testPost`, {
    
    
  method: "POST",
  // body: "纯文本",
  // body: formData, // 会自动设置 content-type 为 multipart/form-data
  // body: urlSearchParams, // 会自动设置 application/x-www-form-urlencoded
  // body: `name=${name}&age=${age}`, // 需要手动设置 "content-type": "application/x-www-form-urlencoded"
  body: JSON.stringify({
    
     name, age }), // 需要手动设置 "content-type": "application/json"
  // 还支持  Blob 或 arrayBuffer,使用的比较少 这个笔者就不举例了
  headers: {
    
    
    // "content-type": "application/x-www-form-urlencoded",
    "content-type": "application/json",
  },
})
  .then((response) => {
    
    
    console.log(response);
    // 转成字符串文本
    return response.text();
  })
  .then((res) => {
    
    
    const resultDiv = document.getElementById("result");
    resultDiv.innerText = res;
  });

fetchtext、FormData、URLSearchParams、search字符串、json字符串、Blob、arrayBufferThe request data type in the format is supported and bodyby default will 'text/plain;charset=UTF-8send the request data in the format.

When the data format FormDatais , it will be automatically set content-typeas the request header multipart/form-dataof .

When the data format URLSearchParamsis , it will be automatically set content-typeas the request header multipart/x-www-form-urlencodedof .

The transfer jsonformat data needs to be converted into jsona string, and the request header also needs to be "content-type": "application/json"set .

mode

mode: Specifies the mode of the request. There are three possible values: cors, same-origin, no-cors

  • cors: The default value, allowing cross-origin requests.
  • same-origin: Only same-origin requests are allowed.
  • no-cors: The request method is limited to GET, POST and HEAD, and only a few simple headers can be used, and cross-domain complex headers cannot be added, which is equivalent to the simple request that can be sent by submitting a form.

cache

cacheAttributes specify how to handle caching. Possible values ​​are as follows:

  • default: The default value, first look for matching requests in the cache.
  • no-store: Request the remote server directly without updating the cache.
  • reload: Directly request the remote server and update the cache.
  • no-cache: Compare the server resource with the local cache, use the server resource only if there is a new version, otherwise use the cache.
  • force-cache: Cache priority, only when there is no cache, the remote server is requested.
  • only-if-cached: Only check the cache, if it does not exist in the cache, a 504 error will be returned.

credentials

credentialsProperty specifies whether to send cookies. Possible values ​​are as follows:

  • same-origin: The default value, cookies are sent for same-origin requests, and not sent for cross-origin requests.
  • include: Cookies are always sent regardless of same-origin requests or cross-domain requests.
  • omit: Never send.

How to judge whether the request is successful

fetch()After sending the request, there is a very important point to note: only when there is a network error or when the connection cannot be made, an error fetch()will be reported. In other cases, no error will be reported, but the request is considered successful. That is to say, even if the status code returned by the server is 4xx or 5xx, fetch()no error will be reported (that is, the Promise will not change to rejectedstatus ).

So how to judge whether the request is successful

The first method is to Response.statusobtain the real status code of the HTTP response through attributes to determine whether the request is successful. That is to judge whether the status is between 200-300.

async function fetchTest() {
    
    
  let response = await fetch(`http://localhost:3000/testGet?name=randy&age=27`);
  if (response.status >= 200 && response.status < 300) {
    
    
    // 请求成功
    return await response.json();
  } else {
    
    
    // 请求失败
    throw new Error(response.statusText);
  }
}

Another way is to judge response.okwhether it is true. Because the value when statusin 200-300between is .oktrue

if (response.ok) {
    
    
 // 请求成功
} else {
    
    
 // 请求失败
}

cancel request

fetch()After the request is sent, if you want to cancel it halfway, it is also supported, and you need to use AbortControllerthe object.

Let's demonstrate

let controller = new AbortController();
let signal = controller.signal;

fetch(`http://localhost:3000/testGet?name=${
      
      name}`, {
    
    
  signal: controller.signal, // 需要传递signal参数
});

// 监听取消
// 也可以通过`controller.signal.aborted`属性判断取消信号是否已经发出。
signal.addEventListener("abort", () => console.log("signal abort!"));

// 取消
controller.abort();

cfcf3a2d-a253-4e55-94f1-da7ee6a43ed9.gif

It should be noted here that there is a one-to-one correspondence controller、signalwith fetchthe request parameters signal. Whichever you call controller.abort()will cancel the corresponding request. Of course, you can also use the same one controllerfor multiple requests, so you can cancel multiple requests at once.

fetchSummary

  1. Support promise, more convenient, fast and efficient to use.
  2. The obtained response needs to be further transformed to get the result we want.
  3. The error of the http status code needs to be judged by ourselves , because the error codes returned by the backend such as 400 and 500 will be resolved on the fetch side and treated as successful.
  4. The data format passed by the request is limited and does not support native js objects.
  5. The request method has also been expanded, not only supports get, post, but also supports put, delete and other request methods
  6. Get and head requests do not support passing request body parameters, and parameters can only be concatenated after the request path.
  7. Support Cancellation Request

Let's take a look at the most usedaxios

axios

axiosIt's not a new thing, but a promise-based HTTP library that encapsulates native Ajax, which can be used in browsers and node.js.

So we need to introduce it before using it

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

Let's look at a simple example

<h3>axios form</h3>
<form id="form1">
  <input type="text" name="name" placeholder="请输入名字" />
  <input type="number" name="age" placeholder="请输入年龄" />
  <input type="button" id="submitBtn1" onclick="request4()" value="提交" />
</form>
<h3>结果</h3>
<div id="result"></div>

We use axios(config)to send a request.

function request4() {
    
    
  const formData = new FormData(document.getElementById("form1"));
  const name = formData.get("name");
  const age = formData.get("age");
  const urlSearchParams = new URLSearchParams(formData);

  axios({
    
    
    url: "http://localhost:3000/testGet",
    params: urlSearchParams,
  }).then((res) => {
    
    
    // 响应数据在data中
    console.log(res.data);
    const resultDiv = document.getElementById("result");
    resultDiv.innerText = JSON.stringify(res.data);
  });
}

Let's see the effect

image.png

For axiosthe focus on configand response results response, let's analyze them one by one.

config

Here I introduce several important configparameters.

url

urlis the server URL for the request

method

HTTP request methods, GET, POST, DELETE, PUTare all set in this property.

baseURL

baseURLwill be automatically urlprepended unless urlis an absolute URL. Our configuration baseURLcan be simplified by setting .url

headers

Set request headers, such as common ones content-type. We won't say much about this.

params

paramsare the URL parameters that will be sent with the request. Must be a plain object or URLSearchParams object.

paramsThe parameter axios set in it will be automatically converted into a search string and spliced ​​to the back of the request address.

data

datais the data sent as the body of the request. Applies only to the request methods 'PUT', 'POST', and 'PATCH'.

transformRequestWhen not set , must be one of the following types:

  • string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  • Browser specific: FormData, File, Blob
  • Exclusive to Node: Streams

When the data format FormDatais axios will automatically set to the request header ofcontent-type .multipart/form-data

When the data format URLSearchParamsis axios will automatically set to the request header ofcontent-type .application/x-www-form-urlencoded

When the data format plain objectis axios will automatically set to the request header ofcontent-type .application/json

When you want to application/x-www-form-urlencodedtransfer data in format, there are usually three methods.

  1. You can pass URLSearchParamsparameters. axios will automatically set content-typeas application/x-www-form-urlencodedthe request header of .
  2. Pass plain object, but you need to manually set content-typeto application/x-www-form-urlencodedthe request header.
  3. qsThe search string is generated by the library for passing. Because when the data format stringis axios will automatically set tocontent-type the request header.application/x-www-form-urlencoded

When you want to send a plain string, you need to manually set the request header content-typeto text/plain.

responseType

responseTypeIndicates the data type of the server response, which can be 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'. After setting, axiosour response results will be converted automatically.

timeout

timeoutSpecify the number of milliseconds for request timeout (0 means no timeout). The request will be aborted if it takes more timeoutthan

withCredentials

withCredentialsIndicates whether it needs to be carried in cross-domain requests cookie. The default is false.

maxContentLength

maxContentLengthDefines the maximum size allowed for response content

After the configuration is understood, let's look at the responseresponse

response

data

dataThe response provided by the server. Our response data is obtained in this property.

status

statusThe HTTP status from the server response. For example, success will return 200.

statusText

statusTextHTTP status information from the server response. For example, success will return "OK".

headers

headersserver response header

config

Requested configuration information.

request

The request object, because axiosit is the right XMLHttpRequestpackage, is an XMLHttpRequestobject.

create instance

We generally don't use it directly axios, but create axiosan instance. axiosSupports creating a new axiosinstance .

const instance = axios.create({
    
    
  baseURL: '/api',
  timeout: 1000,
  headers: {
    
    'content-type': 'application/json'}
});

// ...

Creating an instance has two benefits

First, we can configure the same configuration when creating an instance, so that there is no need to repeat the configuration in each request later.

Second, we can have multiple request instances in one system, and each instance can have its own unique configuration.

instance method

Each axiosinstance can have its own requestrequest method, and there are also convenience methods.

The ones here configwill be merged with the ones used to create the instance above config, and the same configuration will be overwritten.

instance.request(config)

This method is similar axios(config).

instance.get(url, config)

Send a get request directly

instance.delete(url, config)

Send a delete request directly

instance.head(url, config)

Send a head request directly

instance.options(url, config)

Send an options request directly

instance.post(url, data, config)

Send a post request directly, the second parameter is the request data.

instance.put(url, data, config)

Send a put request directly, and the second parameter is the request data.

instance.patch(url, data, config)

Send a patch request directly, the second parameter is the request data.

concurrent method

axiosConcurrent requests are also supported.

For example, send two requests at once.

axios
  .all([
    axios.get("http://localhost:3000/testGet", {
    
    
      params: {
    
     name: "jack" },
    }),
    axios.get("http://localhost:3000/testGet", {
    
    
      params: {
    
     name: "tom" },
    }),
  ])
  .then(
    axios.spread((res1, res2) => {
    
    
      console.log(res1);
      console.log(res2);
    })
  )
  .catch((err) => {
    
    
    console.log(err);
  });

By axios.all([请求1, 请求2...])sending requests in batches, by axios.spread((请求1结果,请求2结果...) => {})getting request results. Note that when one of the requests fails and the entire request fails , catchthe wrong one will be returned promise.

error handling

axiosIt will automatically analyze the response http statuscode , if statusit is between 200 and 300, resloveit will be successful, and the others will be rejected reject.

Of course, if you want to customize the success statusrange, you can configure the request parameter validateStatusmethod

validateStatus: function (status) {
    
    
    return status >= 200 && status < 300; // 默认是200-300
  },

For error handling, there are generally two ways

// 通过 promise 的 catch
axios("http://localhost:3000/testGet", {
    
    
  params: urlSearchParams,
})
  .then((res) => {
    
    
    console.log(res);
  })
  .catch((err) => {
    
    
    console.log(err);
  });

// 通过 try catch
try {
    
    
  const res = await axios("http://localhost:3000/testGet", {
    
    
    params: urlSearchParams,
  });
  console.log(res);
} catch (err) {
    
    
  console.log(err);
}

cancel request

axios()After the request is sent, if you want to cancel it halfway, it is also supported, and you need to use CancelTokenthe object. Generally speaking, fetchthe configuration of and is very similar.

Let's demonstrate

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios("http://localhost:3000/testGet", {
    
    
  cancelToken: source.token, // 需要传递cancelToken
});

// 取消请求(message 参数是可选的)
source.cancel("Operation canceled by the user.");

cb7d5603-a5e1-469d-8a9f-e27ee5a28448.gif

It should be noted here that there is a one-to-one correspondence CancelTokenwith axiosthe request parameters cancelToken. Whichever you call source.cancel()will cancel the corresponding request. Of course, you can also use the same one cancelTokenfor multiple requests, so you can cancel multiple requests at once.

axiosAlso supports the second way to cancel the request

const CancelToken = axios.CancelToken;
let cancel;

axios("http://localhost:3000/testGet", {
    
    
  cancelToken: new CancelToken(function executor(c) {
    
    
    // executor 函数接收一个 cancel 函数作为参数
    cancel = c;
  }),
});

// 取消请求(message 参数是可选的)
cancel("Operation canceled by the user.");

axiosIt fetchseems that there is no canceling listener function.

axiosSummary

  1. Support promise, more convenient, fast and efficient to use.
  2. Through configuration responseType, our response can be automatically converted into the corresponding format, basically no manual processing is required.
  3. The error of the http status code does not need to be judged by ourselves . By default, only the status between 200-300 will be considered successful.
  4. The request body data parameter supports many data formats, and automatically sets the requested content-typevalue according to the format of the data we pass, which is very smart.
  5. The request method has also been expanded, not only supports get, post, but also supports put, delete and other request methods. And provide a corresponding convenient method.
  6. Path parameters are not mandatory to be manually spliced ​​after the path, but can be configured through params, and axios will automatically handle them.
  7. Provides request interception and response interception, which can process requests and responses in a unified manner, and the development efficiency will be higher.
  8. Cancellation requests are supported.

If you are interested in the application in , you can take a look at axiosthe TS package Axios written by the author before.TypeScrit

Backend interface code

The interface is very simple, use node + expressto build

const express = require("express");
const app = express();
var cors = require("cors");

// 允许跨域
app.use(cors());

// 解析表单中 application/x-www-form-urlencoded 格式的数据
app.use(express.urlencoded({
    
     extended: false }));

// 解析表单中application/json格式的数据
app.use(express.json());

// 解析表单中multipart/form-data格式的数据
const multer = require("multer");
const upload = multer();

app.get("/testGet", function (req, res, next) {
    
    
  res.json(req.query);
});

app.post("/testPost", function (req, res, next) {
    
    
  // 将请求体数据直接返回
  res.send(req.body);
});

// 特殊处理multipart/form-data格式的数据
app.post("/testPost2", upload.none(), function (req, res, next) {
    
    
  // 将请求体数据直接返回
  res.send(req.body);
});

app.listen(3000, () => {
    
    
  console.log("serve running on 3000");
});

postscript

Thank you friends for watching patiently. This article is the author's personal study notes. If there is any fallacy, please let me know. Thank you very much! If this article is helpful to you, please follow and like~, your support is the motivation for the author to keep updating!

Guess you like

Origin blog.csdn.net/weixin_38664300/article/details/131008513