再次调用onSearch时取消之前的promise.all
Cancel previous promise.all when onSearch is called again
我有一个反应组件,它有一个自动完成功能,当用户输入超过 3 个字符时调用 onSearch。
一旦发生这种情况,就会调用 Util 文件 (Requests.js) 中的一个函数,并且 returns 一个 axios promise,其中包含从这 3 个字符中搜索到的数据。
有时我需要根据过滤需要多次调用这个函数,所以我循环了很多次我需要并创建一个 axios promises 数组。
然后我promise.all它并在自动完成中显示结果。
我的问题是,如果用户输入 "tes",进程启动可能需要一段时间才能完成,具体取决于他们的搜索词(这很好)。如果他们随后键入添加 "t"(在去抖 window 之后)并使搜索词 "test" 另一个进程启动但它是同步的并等待 "tes" 进程完成之前开始、结束和展示。
很明显第一次调用onSearch需要启动,但是如果后续调用onSearch怎么取消之前的Promise.all?
这是 Observable Streams 的主要用例,但为了保持简单,这里有一个想法。
每当您进行搜索时,增加一个计数器并保存开始搜索时计数器的值。搜索完成后,检查计数器是否改变;如果是,则该搜索不再有效。
React 中的(未测试)示例(因为您的问题被这样标记):
class MyComponent extends React.Component {
state = { items: [] }
searchCounter = 1
constructor() {
super(...arguments)
this.debouncedSearch = debounce(this.search.bind(this), 500)
}
search(e) {
const countBefore = ++this.searchCounter
return axios.get('<url>', { params: { term: e.target.value} }).then(r => {
// Another search happened before the response was done; cancel.
if (countBefore !== this.searchCounter) {
return
}
this.setState({ items: r.data })
})
}
render() {
return (
<div>
<input type="text" onKeyUp={this.debouncedSearch.bind(this)} />
<ul>
{this.state.items.map(item => (
<li key={item.key}>{item.value}</li>
))}
</ul>
</div>
)
}
}
我有一个反应组件,它有一个自动完成功能,当用户输入超过 3 个字符时调用 onSearch。
一旦发生这种情况,就会调用 Util 文件 (Requests.js) 中的一个函数,并且 returns 一个 axios promise,其中包含从这 3 个字符中搜索到的数据。
有时我需要根据过滤需要多次调用这个函数,所以我循环了很多次我需要并创建一个 axios promises 数组。
然后我promise.all它并在自动完成中显示结果。
我的问题是,如果用户输入 "tes",进程启动可能需要一段时间才能完成,具体取决于他们的搜索词(这很好)。如果他们随后键入添加 "t"(在去抖 window 之后)并使搜索词 "test" 另一个进程启动但它是同步的并等待 "tes" 进程完成之前开始、结束和展示。
很明显第一次调用onSearch需要启动,但是如果后续调用onSearch怎么取消之前的Promise.all?
这是 Observable Streams 的主要用例,但为了保持简单,这里有一个想法。
每当您进行搜索时,增加一个计数器并保存开始搜索时计数器的值。搜索完成后,检查计数器是否改变;如果是,则该搜索不再有效。
React 中的(未测试)示例(因为您的问题被这样标记):
class MyComponent extends React.Component {
state = { items: [] }
searchCounter = 1
constructor() {
super(...arguments)
this.debouncedSearch = debounce(this.search.bind(this), 500)
}
search(e) {
const countBefore = ++this.searchCounter
return axios.get('<url>', { params: { term: e.target.value} }).then(r => {
// Another search happened before the response was done; cancel.
if (countBefore !== this.searchCounter) {
return
}
this.setState({ items: r.data })
})
}
render() {
return (
<div>
<input type="text" onKeyUp={this.debouncedSearch.bind(this)} />
<ul>
{this.state.items.map(item => (
<li key={item.key}>{item.value}</li>
))}
</ul>
</div>
)
}
}