簡體   English   中英

如何將每個內部 observable (RxJs) 與外部組合並發出一個數組?

[英]How to combine each inner observable (RxJs) with outer and emit one array?

當我觸發此代碼時:

timer(1000).pipe(
  expand(() => of('a')),
  take(3)
)
  .subscribe(data => alert(data));

我收到 3 次警報:0 警報,'a' 警報,'a' 警報。 我只想得到一個警報,比如說數組[0,a,a]。 如何組合所有值?

您的問題很有趣,並且(正如邁克爾 D 在他的回答中指出的那樣)一個非常具體的用例。

以下代碼的示例,在 StackBlitz 中工作

而不是使用scan (它將為您提供 3 個排放中每一個的當前累積值),我建議reduce ,它只會在源完成時觸發一次。

import { of, timer } from 'rxjs';
import { reduce, expand, take } from 'rxjs/operators';

timer(1000).pipe(
  expand(() => of('a')),
  take(3),
  reduce((acc, val) => { acc.push(val); return acc; }, [])
).subscribe(val => console.log('Output:', val));

// Output: [0, a, a]

這看起來像是一個非常具體的用例,並且有多種方法可以做到這一點。

選項 1: scanfilter運算符

timer(1000).pipe(
  expand(() => of('a')),
  take(3),
  scan((acc, curr) => {
    acc.push(curr);    // <-- push each notification to the array
    return acc;        
  }, []),              // <-- empty array `[]` as seed value 
  filter(values => values.length === 3)    // <-- emit only if notification length is 3
).subscribe(data => alert(data));

請注意,使用scan運算符的 observable 發出 3 個通知: [0][0, 'a'][0, 'a', 'a'] 我們明確限制只發出最后一個通知,因為我們知道它的長度應該是 3(由於take(3) )。

選項 2: scantakeLast運算符

timer(1000).pipe(
  expand(() => of('a')),
  take(3),
  scan((acc, curr) => {
    acc.push(curr);    // <-- push each notification to the array
    return acc;        
  }, []),              // <-- empty array `[]` as seed value 
  takeLast(1)          // <-- emit the last 1 notification
).subscribe(data => alert(data));

選項 3: scanlast運算符

timer(1000).pipe(
  expand(() => of('a')),
  take(3),
  scan((acc, curr) => {
    acc.push(curr);    // <-- push each notification to the array
    return acc;        
  }, []),              // <-- empty array `[]` as seed value 
  last()               // <-- emit the last notification
).subscribe(data => alert(data));

last運算符提供了一個類似於filter運算符的選項。 您可以傳遞一個謂詞,並且只有在滿足該謂詞時才會發出通知。

timer(1000).pipe(
  expand(() => of('a')),
  take(3),
  scan((acc, curr) => {
    acc.push(curr);    // <-- push each notification to the array
    return acc;        
  }, []),              // <-- empty array `[]` as seed value 
  last((values) => values.includes('a'))     // <-- emit only if array contains 'a'
).subscribe(data => alert(data));

選項 4: reduce運算符

請參閱@NathanBeck 的答案

更新

選項 5: toArray運算符

可能最快的解決方案是使用toArray()運算符。

timer(1000).pipe(
  expand(() => of('a')),
  take(3),
  toArray()
).subscribe(data => alert(data));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM