这实际上很简单,dequeue
将创建一个enqueue
将解决的Promise。我们只需要将解析器保持在队列中 - 并且还关心值在出队之前入队的情况,将已经履行的Promise保持在队列中。
class AsyncBlockingQueue {
constructor() {
// invariant: at least one of the arrays is empty
this.resolvers = [];
this.promises = [];
}
_add() {
this.promises.push(new Promise(resolve => {
this.resolvers.push(resolve);
}));
}
enqueue(t) {
// if (this.resolvers.length) this.resolvers.shift()(t);
// else this.promises.push(Promise.resolve(t));
if (!this.resolvers.length) this._add();
this.resolvers.shift()(t);
}
dequeue() {
if (!this.promises.length) this._add();
return this.promises.shift();
}
// now some utilities:
isEmpty() { // there are no values available
return !this.promises.length; // this.length <= 0
}
isBlocked() { // it's waiting for values
return !!this.resolvers.length; // this.length < 0
}
get length() {
return this.promises.length - this.resolvers.length;
}
[Symbol.asyncIterator]() {
// Todo: Use AsyncIterator.from()
return {
next: () => this.dequeue().then(value => ({done: false, value})),
[Symbol.asyncIterator]() { return this; },
};
}
}
我不知道 TypeScript,但大概添加必要的类型注释很简单。
为了获得更好的性能,请使用带有循环缓冲区的 Queue 实现而不是普通数组,例如this one。您也可能只使用一个队列并记住您当前是存储Promise还是解析器。