【问题标题】:Emitting values from dynamically changing array从动态变化的数组中发出值
【发布时间】:2021-07-18 16:40:08
【问题描述】:

我需要模拟一个场景,其中我有一个随机获取新推送值或弹出的数字源数组。该数组被用作计算的源,这些计算应在最后一个完成后开始的循环中重复。每次数组更改时,都应该丢弃以前的计算以使用新值重新开始。

这是我的代码

let nums: number[] = []

const nums$ = new Subject()

timer(2000, 5000).pipe(
    concatMap(n => of(n).pipe(delay(Math.random() * 1000)))
).subscribe(val => {
    nums.push(val)
    nums$.next(nums)
})

nums$.pipe(
    switchMap(n => of(n).pipe(delay(1000)))
).subscribe(val => {
    console.log(val)
    nums$.next(nums)
})

第一个计时器应该模拟对数组所做的更改,而第二个管道将计算表示为延迟。

我的解决方案有点脏,即使传递给 switchMap 内的 of 运算符的值未被识别为数组,所以我不知道如何利用 from 运算符。

【问题讨论】:

    标签: arrays typescript dynamic rxjs subject


    【解决方案1】:

    与其使用Subject 手动发出随机数并更新数组,我认为简单地使用timer 生成随机数,然后使用scan 将它们累积到数组中更简单:

    const nums$ = timer(0, 1500).pipe(
      map(() => Math.ceil(Math.random() * 15)),  
      scan((array, num) => num > 10  
        ? array.slice(0, -1)  // remove last element (33%)
        : array.concat(num)   // add new element (67%)
      , [])
    );
    

    然后,您可以基于nums$ 来确定您的“计算值”(我们将其称为sum$ 作为一个简单的示例):

    const sum$ = nums$.pipe(
      switchMap(numbers => doCalculation(numbers))
    );
    
    function doCalculation(numbers: number[]) {
      return of(numbers.reduce((sum, num) => sum + num, 0)).pipe(delay(1000));
    }
    

    这是一个有效的 StackBlitz 演示。


    传递给 switchMap 中的 of 运算符的值不被识别为数组

    如果您在主题上指定类型,则类型将被正确识别:

    const nums$ = new Subject<number[]>();
    

    【讨论】:

    • 很好的答案,不需要编辑或任何东西,但认为还值得指出的是switchMap(n =&gt; of(n).pipe(delay(1000))) 相当于debounceTime(1000)
    • nums 数组应仅在求和完成后发出,否则如果间隔发出太快,求和(计算)将永远不会完成一次。我使用的计时器太模拟用户交互将新值推送到nums,与我的场景无关。
    猜你喜欢
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 2020-11-10
    相关资源
    最近更新 更多