实例演示axios拦截器和取消请求

axios拦截器

拦截器是什么?
以我的理解,拦截器就是一个回调函数,里面包含了一些逻辑处理的代码,它分为请求拦截器,其在请求发送之前执行,处理一些请求发送之前的逻辑,响应拦截器,其在响应拿到之后,回调函数执行之前执行,处理一些拿到响应数据的逻辑。

为了方便演示,我使用koa写了一个简易的接口,用于处理请求返回数据

const Koa = require('koa');
const router = require('koa-router')();
const jsonp = require('koa-jsonp');
const cors = require('koa-cors');

var app = new Koa();

app.use(cors());
app.use(jsonp());

async function delay(time) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve()
        }, time)
    })
}

router.get('/products1', async (ctx) => {
    await delay(1000 + Math.random() * 1000)
    ctx.body = [{
            id: 1,
            name: 'products1.1'
        },
        {
            id: 2,
            name: 'products1.2'
        },
        {
            id: 3,
            name: 'products1.3'
        }
    ];
});

router.get('/products2', async (ctx) => {
    await delay(1000 + Math.random() * 1000)
    ctx.body = [{
            id: 1,
            name: 'products2.1'
        },
        {
            id: 2,
            name: 'products2.2'
        },
        {
            id: 3,
            name: 'products2.3'
        }
    ];
});

app.use(router.routes());
app.use(router.allowedMethods());
app.listen(4000);

console.log('Server running at http://localhost:4000');

演示

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js"></script>
    <script>
        //添加请求拦截器(回调函数)
        axios.interceptors.request.use(
            config => {
                console.log('request interceptor1 onResolved()')
                return config
            },
            error => {
                console.log('request interceptor1 onRejected()')
                return Promise.reject(error)
            }
        )
        axios.interceptors.request.use(
            config => {
                console.log('request interceptor2 onResolved()')
                return config
            },
            error => {
                console.log('request interceptor2 onRejected()')
                return Promise.reject(error)
            }
        )
        //添加响应拦截器
        axios.interceptors.response.use(
            response => {
                console.log('response interceptor1 onResolved()')
                return response
            },
            error => {
                console.log('response interceptor1 onRejected()')
                return Promise.reject(error)
            }
        )
        axios.interceptors.response.use(
            response => {
                console.log('response interceptor2 onResolved()')
                return response
            },
            error => {
                console.log('response interceptor2 onRejected()')
                return Promise.reject(error)
            }
        )

        axios.get('http://localhost:3000/posts')
            .then(response => {
                console.log('data', response.data);

            })
            .catch(error => {
                console.log('error', error.message)
            })
    </script>
</body>

</html>
执行顺序
请求拦截器2 ------请求拦截器1-------发送ajax请求-------响应拦截器1-------响应拦截器2------响应回调
此流程是通过Promise串联起来的,请求拦截器传递的是config,响应拦截器传递的是response

axios取消发送请求

取消发送请求,顾名思义就是取消正在发送的ajax请求,这在业务场景中是会遇到的

基本流程
  1. 配置cancleToken对象
  2. 缓存用于取消的cancel函数
  3. 在后面特定时机调用cancel取消请求
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>取消请求</title>
</head>

<body>
    <div>
        <button onclick="getOne()">获取商品列表1</button>
        <button onclick="getTwo()">获取商品列表2</button>
        <button onclick="cancelReq()">取消请求</button>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js"></script>
    <script>
        let cancel //用于保存取消请求的函数
        function getOne() {
            axios({
                    url: 'http://localhost:4000/products1',
                    cancelToken: new axios.CancelToken((c) => { //c是用于取消当前请求的函数
                        //保存取消函数,用于之后可能需要取消当前请求
                        cancel = c
                    })
                })
                .then(
                    //不管成功还是失败,都应该没有机会取消了
                    response => {
                        cancel = null
                        console.log('请求1成功了', response.data)
                    },
                    error => {
                        cancel = null
                        console.log('请求1失败了', error.message)
                    }
                )
        }

        function getTwo() {
            axios({
                    url: 'http://localhost:4000/products2',
                })
                .then(
                    response => {
                        console.log('请求2成功了', response.data)
                    },
                    error => {
                        console.log('请求2失败了', error.message)
                    }
                )
        }

        function cancelReq() {
            //alert('取消请求')
            //执行取消请求的函数
            if (typeof cancel === 'function') {
                cancel('强制取消请求')
            } else {
                console.log('没有可取消的请求')
            }
        }
    </script>
</body>

</html>

实例演示

上面的那个例子实现了点击按钮取消发送请求,但是我们会遇到一个情况,用户点击获取列表1的数据之后又点击获取列表2的数据,若列表1和列表2与前台同一位置显示,那么先前请求的列表1的数据的请求是否就可以直接中断而光去请求列表2的数据,这就需要实现在请求一个接口前,取消前面一个未完成的请求

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>取消请求</title>
</head>

<body>
    <div>
        <button onclick="getOne()">获取商品列表1</button>
        <button onclick="getTwo()">获取商品列表2</button>
        <button onclick="cancelReq()">取消请求</button>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js"></script>
    <script>
        let cancel

        function getOne() {
            if (typeof cancel === 'function') {
                cancel('强制取消')
            }
            axios({
                url: 'http://localhost:4000/products1',
                cancelToken: new axios.CancelToken(c => {
                    cancel = c
                })
            }).then(
                response => {
                    cancel = null
                    console.log("请求1成功了");
                },
                error => {
                    if (axios.isCancel(error)) {
                        console.log("取消1导致的错误,不应将cancel置空");
                    } else {
                        cancel = null
                        console.log("请求1失败了");
                    }
                }
            )
        }

        function getTwo() {
            if (typeof cancel === 'function') {
                cancel('强制取消')
            }
            axios({
                url: 'http://localhost:4000/products2',
                cancelToken: new axios.CancelToken(c => {
                    cancel = c
                })
            }).then(
                response => {
                    cancel = null
                    console.log("请求2成功了");
                },
                error => {
                    if (axios.isCancel(error)) {
                        console.log("取消2导致的错误,不应将cancel置空");
                    } else {
                        cancel = null
                        console.log("请求2失败了");
                    }
                }
            )
        }

        function cancelReq() {
            if (cancel) {
                cancel('强制取消')
            } else {
                console.log("没有可以取消的请求");
            }
        }
    </script>
</body>

</html>

因为所有请求都是用的一个cancel,所以cancel为function,则证明前一个请求并没有完成,因为完成请求之后cancel会被置为null

注意这里要写成上面这样,而不是下面

 error => {
                    if (axios.isCancel(error)) {
                        console.log("取消1导致的错误,不应将cancel置空");
                    } else {
                        cancel = null
                        console.log("请求1失败了");
                    }
                }
error => {
cancel = null
console.log("请求1失败了");
}

因为error是异步执行的
比如:点击发送第一次 ---- 点击发送第二次,这时第一次的请求被中断,但是因为error是异步的,所以error的代码并没有马上执行-----点击发送第三次,这是error的代码执行了,cancel被置为null,但此时第二次请求仍在请求中,进入第三次的判断中,cancle不为function,所以无法中断第二次发送的请求,我们使用axios中的isCancel函数可以判断错误是否是因为取消发送请求产生的,若是因为取消发送请求产生的,我们不将cancel置为空就可以解决这个问题

这样虽然完成了要求,但是我们发现重复的地方很多,若是请求多了之后,难道每一个都要再写一遍?有人会想到封装成函数,这里封装成函数并没有改变多少,还是每一个都要调用
这就要使用到我上面提到的拦截器了,拦截器可以对所用的请求(响应)做处理,既然所有的请求(响应)里面都有这样相似的代码,用拦截器在请求发送之前(响应得到之后)一起处理,岂不美哉,这就是拦截器的好处,下面我们来看

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>取消请求</title>
</head>

<body>
    <div>
        <button onclick="getOne()">获取商品列表1</button>
        <button onclick="getTwo()">获取商品列表2</button>
        <button onclick="cancelReq()">取消请求</button>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js"></script>
    <script>
        //添加请求拦截器
        axios.interceptors.request.use((config) => {
            //1.在准备发请求前,取消上一个未完成的请求
            if (typeof cancel === 'function') {
                cancel('强制取消')
            }
            //2.添加一个cancelToken的配置
            config.cancelToken = new axios.CancelToken(c => {
                cancel = c
            })
            return config
        })

        //添加一个响应拦截器
        axios.interceptors.response.use(
            (response) => {
                cancel = null
                return response
            },
            error => {
                if (axios.isCancel(error)) {
                    console.log("取消导致的错误,不应将cancel置空");
                    //中断Promise链
                    return new Promise(() => {})
                } else {
                    cancel = null
                    //非取消导致的错误,将错误向下传递 让请求自己处理
                    return Promise.reject(error)
                    //也可以抛出错误 throw error
                }
            }
        )

        let cancel

        function getOne() {
            axios({
                url: 'http://localhost:4000/products1'
            }).then(
                response => {
                    console.log("请求1成功了");
                },
                error => {
                    //只用处理请求失败的情况,取消请求导致的错误不用处理
                    console.log("请求1失败了");
                }
            )
        }

        function getTwo() {
            axios({
                url: 'http://localhost:4000/products2'
            }).then(
                response => {
                    console.log("请求2成功了");
                },
                error => {
                    console.log("请求2失败了");
                }
            )
        }

        function cancelReq() {
            if (cancel) {
                cancel('强制取消')
            } else {
                console.log("没有可以取消的请求");
            }
        }
    </script>
</body>

</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue配置Axios拦截器可以通过以下步骤实现: 1. 首先,在项目引入Axios库和需要的其他依赖(例如Element UI)。 2. 创建一个Axios实例,可以命名为`instances`,并设置`baseURL`等配置项。 3. 在创建的Axios实例,使用`interceptors`属性来配置响应拦截器。 4. 在响应拦截器,可以通过`instances.interceptors.response.use()`方法来定义成功和失败的处理函数。 5. 在成功处理函数,可以对接口调用成功后的响应进行处理,例如打印日志或进行其他操作。 6. 在失败处理函数,可以对接口调用失败时的情况进行处理,例如打印错误信息或显示提示消息。 7. 最后,导出配置好的Axios实例,以便在项目其他地方使用。 以下是一个示例代码,演示了如何配置VueAxios拦截器: ```javascript import axios from 'axios'; import { Message } from 'element-ui'; import router from '../router'; const instances = axios.create({ baseURL: 'http://localhost', }); instances.interceptors.response.use( success => { console.log('响应拦截器,成功'); // 在这里对成功的响应进行处理 }, error => { console.log('响应拦截器,失败', error); Message.error({ message: error }); // 在这里对失败的响应进行处理 } ); export default instances; ``` 请注意,上述代码是一个示例,你可以根据自己的需求进行修改和扩展。同时,还可以根据需要配置请求拦截器,以实现在所有请求添加统一的内容,例如请求头等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值