Vue network processing - use of axios asynchronous requests, request response interceptor (best practice)

Table of contents

1. axiox

1.1. Introduction to axios

1.2. Basic use of axios

1.2.1. Download the core js file.

1.2.2. Send GET asynchronous request

1.2.3. Send POST asynchronous request

1.2.4. Best practices for sending GET and POST requests

1.3. Request response interceptor

1.3.1. Interceptor explanation

1.3.2. Use of request interceptor

1.3.3. Use of response interceptor

1.3.4. Use of interceptors in Vue scaffolding (best practice)


1. axiox


1.1. Introduction to axios

axios is used to initiate an asynchronous request on the front-end page. After the request, the page does not move, and the response comes back to refresh the part.

1. Why not use ajax?

Official: It is recommended to use ajax technology in jQuery. The jQuery framework is not recommended in Vue, so Vue recommends using the axiox asynchronous request library (axios is not the official library of vue).

2.axios features

  1. XMLHttpRequests can be created from the browser
  2. http requests can be created from node.js.
  3. Support Promise API.
  4. Supports intercepting requests and responses.
  5. Convert request data and response data.
  6. Cancel request.
  7. Automatically convert JSON format data.
  8. The client supports protection against XSRF.

1.2. Basic use of axios

1.2.1. Download the core js file.

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

Ps: It is recommended to download it in advance and put it in a js folder. You can use the reference if needed (convenient for use without Internet access).

1.2.2. Send GET asynchronous request

For example, send a get request to http://localhost:8080/user/login?username=cyk&password=1111 .

Ps: When sending a request through a get request, the parameters carried will not be encapsulated into JSON format.

The front-end code is as follows:

                    axios.get("http://localhost:8080/user/login?username=cyk&password=1111")
                        .then(function (success) { //success 是自定义响应的参数名
                            //返回成功的响应
                            console.log(success); //响应是一个 JSON 格式(axios 自动封装的)
                            console.log(success.data);
                        }).catch(function (error) { //error 是自定义的响应参数名
                            //返回失败的响应(例如,状态码为 403、500......)
                            console.log(error);
                        })
  • then: Indicates the method that needs to be executed to return a successful response.
  • catch: capture the error response and execute the corresponding method.

The backend code is as follows:

@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/login")
    public String login(String username, String password) {
        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return "账号或密码错误,登录失败";
        }
        if(username.equals("cyk") && password.equals("1111")) {
            return "登录成功";
        }
        return "账号或密码错误,登录失败";
    }

}

After the front end sends a response, the effect is as follows:

explain:

  1. CORS is the solution to cross-domain problems (cross-domain problems occur here, and the system will prompt you with solutions). Because the front end is opened through the Live Server plug-in, port 5500 is automatically assigned, which means that your request is from port 5500 is sent, but the backend receives the response on port 8080, which leads to cross-domain problems (the browser prohibits this operation)
  2. Since the response is an error, it is caught by axios' catch and displayed on the console via console.log.

In microservice projects, it needs to be solved through Gataway. Currently, for the convenience of demonstration, Spring Boot is used for processing, so you only need to add the @CrossOrigin annotation on the controller layer. Resolve cross-domain issues.

After adding the annotation, restart the backend service and resend the request. The effect is as follows:

You can see that the response received by the front end is a response in json format.

1.2.3. Send POST asynchronous request

For example, send a POST request to http://localhost:8080/user/login , carrying JSON format parameters (axios automatically converts): { "username"="cyk", "password"='1111"}.

The front-end code is as follows:

                    axios.post("http://localhost:8080/user/login", { username: "cyk", password: "1111" })
                        .then(function (success) {
                            //返回成功的响应
                            console.log(success); //响应是一个 JSON 格式(axios 自动封装的)
                            console.log(success.data);
                        }).catch(function (error) {
                            //返回失败的响应(例如,状态码为 403、500......)
                            console.log(error);
                        })

When the backend receives, it must create a corresponding entity class and add the @RequestBody annotation to receive JSON format data.

@Data
public class Userinfo {

    private String username;
    private String password;

}
@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {

    @RequestMapping("/login")
    public String login(@RequestBody Userinfo userinfo) {
        if(userinfo == null || !StringUtils.hasLength(userinfo.getUsername())
                || !StringUtils.hasLength(userinfo.getPassword())) {
            return "账号或密码错误,登录失败";
        }
        if(userinfo.getUsername().equals("cyk") && userinfo.getPassword().equals("1111")) {
            return "登录成功";
        }
        return "账号或密码错误,登录失败";
    }

}

After sending the request, the effect is as follows:

1.2.4. Best practices for sending GET and POST requests

Through the above method, it is possible to send GET and POST requests. Friends who observe carefully will find that each time a request is sent, the requested IP and port number need to be written. The coupling degree is too high. Once the IP and port of the server need to be changed later, No., everything needs to be changed.

Therefore, we can create an axios instance first, write the server's IP and port in advance, and then send the corresponding route through this instance when we need to send a request later.

Specifically, an instance is created through axios.create({}). An object is passed in. There are many parameters in the object. We only need to know the two most commonly used ones.

  • baseURL: Specify the requested destination server ip and port.
  • timeout: timeout time (unit is ms). If no response is received after the timeout, a timeout error will be reported directly.

Examples are as follows:

        let axiosInstance = axios.create({
            baseURL: "http://localhost:8080",
            timeout: 5000
        });

        let app = new Vue({
            el: "#app",
            methods: {
                httpGet() {
                    axiosInstance.get("/user/login?username=cyk&password=1111")
                        .then(function (success) { //success 是自定义响应的参数名
                            //返回成功的响应
                            console.log(success); //响应是一个 JSON 格式(axios 自动封装的)
                            console.log(success.data);
                        }).catch(function (error) { //error 是自定义的响应参数名
                            //返回失败的响应(例如,状态码为 403、500......)
                            console.log(error);
                        })
                },
                httpPost() {
                    axiosInstance.post("/user/login", { username: "cyk", password: "1111" })
                        .then(function (success) {
                            //返回成功的响应
                            console.log(success); //响应是一个 JSON 格式(axios 自动封装的)
                            console.log(success.data);
                        }).catch(function (error) {
                            //返回失败的响应(例如,状态码为 403、500......)
                            console.log(error);
                        })
                }
            }
        });

Ps: There are other request types, and the request format is almost the same as POST. Except that the DELETE request is almost the same as GET, and the parameters generally passed are only id (the backend deletes information based on the id).

1.3. Request response interceptor

1.3.1. Interceptor explanation

It is used to process public parameters and responses in axios in a unified manner to reduce code redundancy when axios sends requests or receives responses.

1.3.2. Use of request interceptor

Request interceptor: For example, in a microservice architecture, we often use Token tokens as user authentication identifiers, which means that every request sent by the front end needs to add a Token in the header, which requires the use of a request interceptor. Perform unified processing.

Here we print it out to see what the request interceptor intercepted:

        //创建统一的实例
        let axiosInstance = axios.create({
            baseURL: "http://localhost:8080",
        });

        // axios.interceptors.request.use 这里不使用这种单一创建的方法,而是使用统一的实例,如下

        //请求拦截器
        axiosInstance.interceptors.request.use(function (config) { // 做项目建议还是用箭头函数:(config) => {} ,属于懒汉加载,提高速度
            //自定义参数名,拦截下来的是请求的配置
            console.log(config);
            return config; //这里必须要返回这个参数! 否则报错!
        });

        let app = new Vue({
            el: "#app",
            methods: {
                httpGET() {
                    axiosInstance.get("/user/sayHi")
                        .then(function (success) {
                            console.log(success.data);
                        });
                }
            }
        });

The backend code is as follows:

    @RequestMapping("/sayHi")
    public String sayHi(String token) {
        if(StringUtils.hasLength(token)) {
            System.out.println(token);
        }
        return "hello!";
    }

The effect is as follows:

As you can see, we use the request interceptor to modify the configuration before the request is sent to the server.

For example, intercept the request and add the token parameter at the end of the url.

        axiosInstance.interceptors.request.use(function (config) {
            console.log(config);
            if (config.url.indexOf("?") == -1) {
                // url 后面没有设置参数. 添加参数时注意加上 "?"
                config.url += "?token=1234";
            } else {
                config.url += "&token=1234";
            }
            return config;
        });

The effect is as follows:

1.3.3. Use of response interceptor

Response interceptor: intercepts all responses sent from the backend and processes them uniformly.

For example, error responses (catch) can be handled uniformly.

        axiosInstance.interceptors.response.use(function (response) { //自定义响应参数名
            console.log(response);
            if (response.status == 500) {
                alert("服务器出现错误");
            }
            //其他错误处理...
            return response; //这里必须返回 response,否则报错
        });

The effect is as follows:

Ps: With the unified handling of unified response exceptions, the catch part in axios can be omitted.

1.3.4. Use of interceptors in Vue scaffolding (best practice)

In the vue scaffolding, according to the standard development method, a utils folder will be created in the src directory, and then a request.js file will be created in this folder, specifically used to encapsulate axios instances and interceptors. 

The following code:

import axios from 'axios'

//构建统一 axios 实例
const instance = axios.create({
    baseURL: "http://localhost:8060",
    timeout: 5000
});

instance.interceptors.request.use(config => {
    //加入 Token 数据...
    //例如: 将 Token 从 localStorage 中取出来,加入到请求头中
    let username = localStorage.getItem("username");
    let token = localStorage.getItem("token");
    //2.将 用户名 和 token 添加到 config 中
    config.headers.set("username", username);
    config.headers.set("token", token);

    console.log("请求拦截器");
    return config;
});

instance.interceptors.response.use((success => {
    //业务逻辑处理...
    console.log("成功:响应拦截器");
    return success;
}), error => {
    //业务逻辑处理...
    //例如:
    if (error.response.status == 403) {
        //跳转主页面
        router.push({ name: "Login" });
        alert("很抱歉,您没有权限,请登录!");
    }

    //将异常传递给下一个处理
    return Promise.reject(error);
})

// //暴露 instance 实例对象(这样在其他地方就可以直接使用 instance)
export default instance;

Guess you like

Origin blog.csdn.net/CYK_byte/article/details/133856894