取消请求

问题存在

首先来看bug发生的场景:现在有一个搜索框,需要实现一个功能,搜索联想,当用户输入不同的关键词,下方可以出现不同的联想。

现在用户输入了一个1,联想下返回是11,用户输入2,联想返回是2,以此类推。这种情况下网络情况我们是不能保证的,所以可能出现不同相应返回的时间不一致的情况,如果2的返回早于一的返回,那么用户得到的搜索关键词,可能是上一次发出的,从而导致bug。

1
2
3
4
5
6
7
8
9
10
11
12
const input = document.querySelector('input');
function dosomething(){
//将返回替换到联想栏当中
}
input.oninput = async()=> {
const response = fetch.get({
'http···?key='+input.value
}).then((res)=>{
res.json();
})
dosomething(response);
}

错误的解决方法

防抖,防抖并不能解决这个问题,当我的两次输入超过了防抖设置的时间间隔,两次请求同同样都会发出,这个时候我们还是不能控制接受到的时间

正确的解决方法

本质上就是要取消上一次发出去的请求,在http请求头里有一个signal字段,这个字段可以用来传递实时通信的控制信号,比如会话的建立、结束、媒体流的控制等指令
在fetch api中,可以在请求头字段添加一个signal字段

1
2
3
4
5
6
7
8
9

cosnt controller = new AbortController();
const response = fetch.get({
'http···?key='+input.value
{
signal: controller.signal
}
})

通过这种方法我们就可以控制某一次的请求的中止,所以现在的核心方法就是获取上一次请求的控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const input = document.querySelector('input');
function dosomething(){
//将返回替换到联想栏当中
}
//将控制器设为当前作用域的全局变量
const controller = null;

input.oninput = async()=> {
if(controller){
controller.abort()
}//取消上一次的请求。
controller = new AbortController();
const response = fetch.get({
'http···?key='+input.value
}).then((res)=>{
res.json();
})
dosomething(response);
}