我有一个搜索栏,每个字母的结果都会更新,但是例如,当用户快速键入3个字母时,先前的请求不会被取消,因此在获得结果之前会有很长的延迟。
我已经读过https://github.com/axios/axios#cancellation,也许我有点累,但是我很难在项目中添加它。它几乎起到了相反的作用,现在需要永远。 您有任何建议吗?或者,您是否推荐一个好的教程,以便我能理解?
<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;
}
);
}
}
答案 0 :(得分:2)
我能够使它工作。.诀窍是在启动API调用之前检查取消令牌是否存在。.我不得不移动CancelToken
和{{1} } cancel
对象/组件之外的变量。
此示例在GitHub上搜索存储库...
Vue
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();
}
}
}
});
已取消的请求:
答案 1 :(得分:1)
问题是您要在newSearch中创建一个新的canceltoken,然后取消它而不是原来的。 如果将源保存在Vue组件上,则可以签入newSearch是否存在,然后仅取消。 Promise帖子完成后,您将再次删除源,这样就可以在不需要(或可能不需要)时取消它。
{
searchItems() {
let filters = {
q: this.query
};
const CancelToken = axios.CancelToken;
this.searchItemsSource = CancelToken.source();
axios.post('/Items/find', filters, {
cancelToken: this.searchItemsSource.token
})
.catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
}
})
.then(
response => {
this.searchItemsSource = undefined;
if(this.Items!=null){
response.data.forEach(element => {
this.Items.push(element);
});
}
else
this.Items=response.data;
}
);
},
newSearch(){
if (this.searchItemsSource) {
this.searchItemsSource.cancel('Cancel previous request');
}
this.countItems();
this.searchItems();
},
}
关于此代码的旁注;实际上,我将取消上一个请求的方法移到了searchItems方法中,因为同时拥有两个正在运行的调用没有任何意义。看起来更像这样:
{
searchItems() {
let filters = {
q: this.query
};
if (this.searchItemsSource) {
this.searchItemsSource.cancel('Cancel previous request');
}
const CancelToken = axios.CancelToken;
this.searchItemsSource = CancelToken.source();
axios.post('/Items/find', filters, {
cancelToken: this.searchItemsSource.token
})
.catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
}
})
.then(
response => {
this.searchItemsSource = undefined;
if(this.Items!=null){
response.data.forEach(element => {
this.Items.push(element);
});
}
else
this.Items=response.data;
}
);
},
newSearch(){
this.countItems();
this.searchItems();
},
}
这时您可以问自己是否完全需要newSearch方法,您可以将其删除并将countItems调用也移到searchItems中。这一切都取决于您的其余代码和功能。