首页 > 解决方案 > 从动态变化的数组中发出值

问题描述

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

这是我的代码

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)
})

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

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

标签: arraystypescriptdynamicrxjssubject

解决方案


我认为不是使用 aSubject手动发出随机数并更新数组,而是简单地使用 atimer生成随机数,然后使用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%)
  , [])
);

然后,您可以将您的“计算值”(让我们称之为sum$一个简单的例子)基于nums$

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[]>();

推荐阅读