Ric*_*ler 6 javascript asynchronous promise async-await typescript
所以这是一个矛盾的说法:我想在javascript/typescript中创建一个异步阻塞队列(如果你可以在没有打字稿的情况下实现它,那很好).基本上我想实现类似Java的BlockingQueue
预期,而不是实际阻塞它,它将是异步的,我可以等待出列.
这是我想要实现的接口:
interface AsyncBlockingQueue<T> {
enqueue(t: T): void;
dequeue(): Promise<T>;
}
Run Code Online (Sandbox Code Playgroud)
我会像这样使用它:
// enqueue stuff somewhere else
async function useBlockingQueue() {
// as soon as something is enqueued, the promise will be resolved:
const value = await asyncBlockingQueue.dequeue();
// this will cause it to await for a second value
const secondValue = await asyncBlockingQueue.dequeue();
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
实际上它很简单,dequeue
会创造一个enqueue
可以解决的承诺.我们只需要将解析器保留在一个队列中 - 并且还要关注值在出列之前入队的情况,并将已经完成的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]() {
return {
next: () => this.dequeue().then(value => ({done: false, value}))
};
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道TypeScript,但可能只是添加必要的类型注释很简单.
为了获得更好的性能,请使用带有循环缓冲区的队列实现,而不是普通数组,例如这个.您也可以只使用一个队列,并记住您当前是否存储承诺或解析器.
这只是@Bergi 的答案,但是使用 typescript + generics 进行了一些修改,以使其在我的 typescript 窥视的严格模式下工作。
class AsyncBlockingQueue<T> {
private _promises: Promise<T>[];
private _resolvers: ((t: T) => void)[];
constructor() {
this._resolvers = [];
this._promises = [];
}
private _add() {
this._promises.push(new Promise(resolve => {
this._resolvers.push(resolve);
}));
}
enqueue(t: T) {
if (!this._resolvers.length) this._add();
const resolve = this._resolvers.shift()!;
resolve(t);
}
dequeue() {
if (!this._promises.length) this._add();
const promise = this._promises.shift()!;
return promise;
}
isEmpty() {
return !this._promises.length;
}
isBlocked() {
return !!this._resolvers.length;
}
get length() {
return this._promises.length - this._resolvers.length;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
912 次 |
最近记录: |