我正在使用vue-infinite-loader来显示用户并在滚动上加载它们。另外,我有一个按名称的过滤器。
我遵照https://peachscript.github.io/vue-infinite-loading/guide/use-with-filter-or-tabs.html
给出的说明下面是过滤器的HTML:<input v-model="name" type="text" class="form-control" placeholder="Search by name" @input="changeName">
这里是相关的值方法:
methods: {
infiniteHandler: function ($state) {
console.log(api + this.parameter);
axios.get(api + this.parameter, {params: {page: this.page}}).then((result) => {
if (result.data.meta.current_page <= result.data.meta.last_page) {
this.page += 1;
this.users.push(...result.data.data);
$state.loaded();
} else {
$state.complete();
}
});
},
changeName() {
this.parameter= '?name=' + encodeURIComponent(this.name);
this.page = 1;
this.users = [];
this.infiniteId += 1;
},
如果我输入now "Max"作为输入文本域中的用户名,则changeName
执行3次,M
、Ma
和Max
分别执行一次。问题是,调用是并行的,这意味着从Max
开始的用户也将匹配从Ma
和M
开始的用户。因此,我突然有了重复的用户,他们的名字不是以Max
开头,而是以Marjon
开头,等等。
我实际上在changeName()
内部有一个超时,以防止每次击键时HTTP调用:
changeName() {
clearTimeout(this.timeout);
this.timeout = setTimeout(function() { ...}, 200);
},
然而,上面的理论问题仍然可能发生在这里(如果按键和HTTPS调用都需要超过200ms)。
如果用户输入"然后是&;Max"axios调用由"Ma"被停止,并立即调用"Max"执行。
要取消axios请求,可以使用canceltoken
请注意,当调用infiniteHandler
时,以前的请求是如何被取消的,并且当请求完成时取消令牌将被删除
methods: {
infiniteHandler: function ($state) {
console.log(api + this.parameter);
// _cancelSource is truthy if there's a request "in flight"
if (this._cancelSource) {
this._cancelSource.cancel('new search');
this._cancelSource = null;
}
// get a new canceToken
this._cancelSource = axios.CancelToken.source();
axios.get(api + this.parameter, {
cancelToken: this._cancelSource.token
params: {page: this.page}
}).then((result) => {
// no need to cancel now
this._cancelSource = null;
if (result.data.meta.current_page <= result.data.meta.last_page) {
this.page += 1;
this.users.push(...result.data.data);
$state.loaded();
} else {
$state.complete();
}
});
},
如果取消不完全工作-您可以链接axios返回的承诺
然而,我不认为这是必需的
如果您不想通过删除cancelToken代码 来取消之前的请求(出于其他目的),可能仍然有用。
methods: {
infiniteHandler: function ($state) {
console.log(api + this.parameter);
// initialise the promise for first time
this._requestPromise = this._requestPromise || Promise.resolve();
// _cancelSource is truthy if there's a request "in flight"
if (this._cancelSource) {
this._cancelSource.cancel('new search');
this._cancelSource = null;
}
// get a new canceToken
this._cancelSource = axios.CancelToken.source();
// chain on to the previous request
// NOTE: cancelling the previous request will make it reject ...
// but that can be handled
this._requestPromise = this._requestPromise
// handle any cancelled previous request
// or previous request rejections
// we still want to do this one if the previous rejected
.catch(() => {})
.then(() => {
axios.get(api + this.parameter, {
cancelToken: this._cancelSource.token
params: {page: this.page}
}).then((result) => {
// no need to cancel now
this._cancelSource = null;
if (result.data.meta.current_page <= result.data.meta.last_page) {
this.page += 1;
this.users.push(...result.data.data);
$state.loaded();
} else {
$state.complete();
}
});
});
},
您可以使用axios的CancelToken在另一个axios请求开始之前取消axios请求
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get(api + this.parameter, {
params: {page: this.page}},
cancelToken: source.token
).then((result) => {
if (result.data.meta.current_page <= result.data.meta.last_page) {
this.page += 1;
this.users.push(...result.data.data);
$state.loaded();
} else {
$state.complete();
}
});
(代码未测试,但给出了想法)