vue.js - Search with axios: cancel previous request when new character
问题描述
I have a searchbar, the results are updated on each letter, but when the user types 3 letters quickly for example, the previous requests are not cancelled so there is a ugly delay before he get his results.
I have read this https://github.com/axios/axios#cancellation and maybe I am a bit tired but I struggle very much adding it in my project. It is almost doing the opposite effect, it now takes forever. Do you have any suggetsion or maybe do you recommend a good tutorial so that I could understand this?
<input v-model="query" type="text" class="form-control" placeholder="Runner name or description"
aria-label="Runner name or description"
aria-describedby="basic-addon2">
watch: {
query: {
handler: _.debounce(function () {
this.newSearch()
}, 100)
}
},
methods: {
searchItems() {
let filters = {
q: this.query
};
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.post('/Items/find', filters, {
cancelToken: source.token
})
.catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
}
})
.then(
response => {
if(this.Items!=null){
response.data.forEach(element => {
this.Items.push(element);
});
}
else
this.Items=response.data;
}
);
},
newSearch(){
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
source.cancel('Cancel previous request');
this.countItems();
this.searchItems();
},
showMore(){
this.startindex = this.startindex+this.nbrows;
this.searchItems();
},
countItems(){
this.countItems=10;
let filters = {
q: this.query
};
axios.post('/Items/count', filters).then(
response => {
this.countItems=response.data;
}
);
}
}
解决方案
我能够让它工作.. 诀窍是在启动 API 调用之前检查取消令牌是否存在等等.. 我不得不将CancelToken
andcancel
变量移到Vue
对象/组件之外..
此示例在 GitHub 中搜索存储库...
var cancel;
var CancelToken = axios.CancelToken;
new Vue({
el: "#app",
data: {
query: "",
results: "",
isLoading: false
},
methods: {
clear() {
this.isLoading = false;
this.results = "";
this.query = "";
},
handleSearch: _.debounce(function() {
this.preApiCall();
}, 300),
preApiCall() {
if (cancel != undefined) {
cancel();
console.log("cancelled");
}
this.apiCall(this.query);
},
apiCall(query) {
if (query !== "") {
this.isLoading = true;
axios({
method: "get",
url: "https://api.github.com/search/repositories",
cancelToken: new CancelToken(function executor(c) {
cancel = c;
}),
params: {
q: query
}
}).then(res => {
this.results = JSON.parse(JSON.stringify(res.data.items));
this.isLoading = false;
}).catch(err => {
this.results = err.message;
throw Error(err.message);
this.isLoading = false;
});
} else {
this.clear();
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
<div id="app">
<input v-model="query" @keyup.stop="handleSearch" type="text" class="form-control" placeholder="Search">
<button @click.stop="clear">Clear</button>
<div v-if="isLoading">Loading...</div>
<ul v-if="results !== ''">
<li v-for="(r, index) in results" :key="index">
{{ r.name }}
</li>
</ul>
</div>
[ CodePen 镜像]
取消的请求:
推荐阅读
- graphics - 处理,简单的“光线追踪”引擎“目标虚拟机初始化失败”
- lisp - 我很难理解为什么当我更改列表中的某些值而其他 Lisp 数据没有更改时
- c# - 如何解决 API 29 中的函数问题?
- c++ - 如何强制覆盖子类中的虚函数
- php - json_decode 除了解码 JSON 有什么特殊用途吗?
- python - 具有 k 步的 Python 反向列表,就地运算符与标准运算符
- python - 每次尝试都给出一个提示(猜数字游戏)
- javascript - 加载时如何聚焦和选择输入?
- javascript - 在鼠标悬停时更改 React 中的背景视频
- html - 悬停时如何更改不是方形的img链接的颜色