我有一个类, QueueManager ,它管理一些队列。
QueueManager提供3个API
deleteQueue(queueName: string): Observable<void>
createQueue(queueName: string): Observable<string>
listQueues(): Observable<string>
:可观察` deleteQueue
是一劳永逸的API,从某种意义上说,它在完成工作并删除队列后不会返回任何信号。同时createQueue
如果已经存在同名队列,则会失败。
listQueues()
返回由 QueueManager 管理的队列的名称。
我需要创建一个逻辑,该逻辑删除队列并重新创建它。所以我的想法是做类似的事情
deleteQueue(queueName)
方法listQueues
方法,直到返回的结果表明queueName
不再存在createQueue(queueName)
我认为我不能使用retry
或repeat
运算符,因为它们重新订阅了源,在这种情况下,这意味着要多次发出deleteQueue
命令,这是我需要避免的事情。
所以我想做的是像
deleteQueue(queueName).pipe(
map(() => [queueName]),
expand(queuesToDelete => {
return listQueues().pipe(delay(100)) // 100 ms of delay between checks
}),
filter(queues => !queues.includes(queueName)),
first() // to close the stream when the queue to cancel is not present any more in the list
)
这种逻辑似乎确实有效,但是在我看来有点笨拙。有没有更优雅的方法来解决这个问题?
答案 0 :(得分:0)
需要行map(() => [queueName])
是因为expand
还会从其可观察的源中发出值,但我认为仅从它来看并不明显。
您可以使用repeat
,您只需要订阅可观察的listQueues
,而不是deleteQueue
。
我也将延迟设置为之前 listQueues
,否则,您将等待发出已经从API返回的值。
const { timer, concat, operators } = rxjs;
const { tap, delay, filter, first, mapTo, concatMap, repeat } = operators;
const queueName = 'A';
const deleteQueue = (queueName) => timer(100);
const listQueues = () => concat(
timer(1000).pipe(mapTo(['A', 'B'])),
timer(1000).pipe(mapTo(['A', 'B'])),
timer(1000).pipe(mapTo(['B'])),
);
const source = deleteQueue(queueName).pipe(
tap(() => console.log('queue deleted')),
concatMap(() =>
timer(100).pipe(
concatMap(listQueues),
tap(queues => console.log('queues', queues)),
repeat(),
filter(queues => !queues.includes(queueName)),
first()
)
)
);
source.subscribe(x => console.log('next', x), e => console.error(e), () => console.log('complete'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.4/rxjs.umd.js"></script>