异步类型提前输入缓冲区或队列 [英] Async type ahead input buffer or queue
问题描述
我正在处理类型提前输入组件,实现的一部分是可取消承诺的队列或缓冲区FIFO.
I'm working on a type ahead input component and part of my implementation is a queue or buffer FIFO of cancelable promises.
因为键入可能比每个字母上的异步请求快得多,所以我必须取消上一个请求,因此,如果前一个诺言比当前的诺言慢,状态不会被无意更改.
Because the typing can happen much faster than the async requests on each letter, I have to cancel the previous request, so that state is not inadvertently changed if the previous promise is slower than the current.
我当前的实现效果很好,但是我想知道是否有必要维护队列而不是单个引用.队列永远不会真正增长一次只能保留一个以上的承诺,对吧?
My current implementation works well, but I'm wondering if its necessary to maintain a queue vs. a single reference. The queue should never really grow to retain more than one promise at a time, right?
_onChangeEvent(str) {
var self = this;
var str = String(str) || '';
var toBeCanceled = null;
// set state return false if no str
// and shift off last request
if (!str) {
if (this.requestQueue.length > 0) {
toBeCanceled = this.requestQueue.shift();
toBeCanceled.cancel();
}
this.setState({results: [], loading: false, value: ''});
return false;
} else {
this.setState({loading: true, value: str});
}
// setup a cancelable promise and add it to the queue
// this API spoofer should eventually be a dispatch prop
var cancelable = CancelablePromise(APISpoofer(str));
cancelable
.promise
.then((res) => {
var sorted = res.found.sort((a, b) => {
var nameA = a.toLowerCase(), nameB = b.toLowerCase();
if(nameA < nameB) return -1;
if(nameA > nameB) return 1;
return 0;
}).slice(0, 4);
// set state and shift queue when resolved
return self.setState({
results: sorted,
loading: false,
value: str
}, () => {
self.requestQueue.shift();
});
})
.catch((err) => {
return err;
});
// check len of requestQueue and push
if(this.requestQueue.length === 0) {
this.requestQueue.push(cancelable);
} else {
// cancel previous and push
toBeCanceled = this.requestQueue.shift();
toBeCanceled.cancel();
this.requestQueue.push(cancelable);
}
}
保持一个值的队列是否有问题?还有,这种问题有名字吗?
Is there a problem with maintaining a queue of one value? Also, is there a name for this kind of problem?
推荐答案
由于您的代码会在发送新请求之前立即取消任何进行中的请求,因此您的队列将永远不会包含一个以上的元素.因此,使用队列毫无用处,简单的 currentRequest
字段足以确保您只能处理最新请求,而不管其处理顺序如何.
As your code immediately cancels any in-flight request before sending a new one, your queue will never contain more than one element. So it's useless to use a queue, a simple currentRequest
field is enough to ensure you can handle only the most recent request, no matter in what order they are processed.
提前输入控件的常见做法是限制输入事件,即在实际发送AJAX请求之前,等待一小段时间进行另一项更改.这样可以避免在用户快速键入多个字母时发送太多请求.
A common practice in type-ahead controls is to throttle the input events, i.e. wait a short amount of time for another change before actually sending an AJAX request. This avoids sending too many requests when users type several letters in a quick fashion.
如果您愿意使用反应式编程技术(例如,使用RxJS http://reactivex.io/.
Both of those problems can be abstracted from your code if you are willing to use reactive programming techniques, e.g. using RxJS http://reactivex.io/.
实际上,在以下RxJS页面的某个地方,您会找到一个完全做到这一点的示例:观察输入更改,至少需要2个字符,反跳,查询Web服务,然后处理结果:
In fact somewhere down on the following RxJS page you will find an example that does exactly that: observing input changes, requiring at least 2 chars, debouncing, querying a webservice and then handling the results: https://github.com/Reactive-Extensions/RxJS
这篇关于异步类型提前输入缓冲区或队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!