#rxjs
Вопрос:
Я пытаюсь очистить очередь/буфер неизвестной длины, которая ограничена пустой строкой.
Пример: in->["","P2","P1"]->out
Существует вызов, который возвращает следующий элемент в очереди. function getNext():Observable<string>
Это наблюдаемое холодно и недолговечно. Так что единственное, что я мог сделать, это:
getNext().subscribe(console.log,console.err,()=>console.log("complete"));
--> "P1"
--> "complete"
getNext().subscribe(console.log,console.err,()=>console.log("complete"));
--> "P2"
--> "complete"
getNext().subscribe(console.log,console.err,()=>console.log("complete"));
--> ""
--> "complete"
Я хотел бы превратить его в полукороткоживущую наблюдаемую, которая выдает значения до тех пор, пока не будет выдана пустая строка, а затем завершится.
theBetterGetNext().subscribe(console.log,console.err,()=>console.log("complete"));
--> "P1"
--> "P2"
--> ""
--> "complete"
Для фиксированной длины это было бы легко. of(1,2,3).pipe(mergeMap(()=>getNext()))
но я борюсь с неизвестной длиной. Не могли бы вы, пожалуйста, подвести меня к решению?
Ответ №1:
Я думаю repeatWhen
, это ваш оператор:
const theBetterGetNext = () => getNext().pipe(
repeatWhen(value => value === "" ? EMPTY : of(null))
);
theBetterGetNext().subscribe(
console.log,
console.error,
() => console.log("complete")
);
Это должно повторно подписаться на источник, пока значение не станет пустым (=== «»)
Редактировать: Я делаю предположение здесь: вам не нужно снова звонить getNext
, чтобы получить новое значение, но вы можете повторно использовать исходное наблюдаемое…
Я просто нашел другое решение, если вам нужно позвонить getNext()
:
const theBetterGetNext = () => getNext().pipe(
expand(value => value === "" ? EMPTY : getNext())
);
theBetterGetNext().subscribe(
console.log,
console.error,
() => console.log("complete")
);
Комментарии:
1. Хорошо, не ОП, но расширение отлично подходит для этой проблемы.
Ответ №2:
Вы можете использовать takeWhile
оператор для получения значений только в том случае, если они не являются пустой строкой.
Как только вы получите пустую строку, наблюдаемое завершится:
of(1, 2, 3)
.pipe(
mergeMap(() => getNext()),
takeWhile(val => val !== "")
)
.subscribe(
console.log,
console.error,
() => console.log("complete")
);
Комментарии:
1. похоже на то, что я хочу, но то, как вы это сделали, предполагает максимум три операции, верно? Из-за: из(1,2,3). Я мог бы использовать interval (), чтобы выдавать бесконечное количество возможностей для чтения, но я не хочу ждать во время возможностей для чтения. Есть ли что-то более подходящее тогда, интервал()?
2. хорошо, я руководствовался вашим примером, используя
mergeMap
. Если вам нужно постоянно звонитьgetNext
, тоexpand
, вероятно, это ваш лучший выбор, как предложил оливарра1.