Rxjs 从不断增长的数组重复发射值

Rxjs 从不断增长的数组重复发射值,rxjs,rxjs6,Rxjs,Rxjs6,快速上下文:我正在显示一个“实时”图像幻灯片,这意味着随着图像的显示,用户可以上传图像&这些新图像最终应该会显示出来。这是“无限”,意味着一旦所有图像都被发射出来,我想在第一个图像处重新启动。新传入的图像应转到队列的末尾,并在我循环返回到它们时发出 我提出了一个我认为肮脏且不正确的解决方案,归结起来是: 常量srcArray=[-2,-1]; const userImageUpload$=间隔(2000)。管道( 点击((val)=>srcArray.push(val)) ).subscribe

快速上下文:我正在显示一个“实时”图像幻灯片,这意味着随着图像的显示,用户可以上传图像&这些新图像最终应该会显示出来。这是“无限”,意味着一旦所有图像都被发射出来,我想在第一个图像处重新启动。新传入的图像应转到队列的末尾,并在我循环返回到它们时发出

我提出了一个我认为肮脏且不正确的解决方案,归结起来是:

常量srcArray=[-2,-1]; const userImageUpload$=间隔(2000)。管道( 点击((val)=>srcArray.push(val)) ).subscribe(); const liveImages$=zip(间隔(1000),from(srcArray)).pipe( 映射([a,b])=>b), 重复() ).subscribe((val)=>console.log(“Image”+val));
这里我们有一些“图像”的起始数组。
userImageUpload$
代表了新图像进入的想法。当我得到一个时,我将它推入起始阵列
liveImages$
表示我希望发出的值。这在技术上是可行的,但改变这个共享的全局阵列感觉很糟糕,可能会导致问题。是否有一个很好的解决方案,可以通过使用主题来做到这一点?我想不出解决方案。

使用
行为主题
更有意义。我认为您的解决方案很好,这个答案的区别在于,当图像上传时,即阵列更新时,您会收到通知,方法是使用
imageStore
启动流

const imageStore=new BehaviorSubject([-2, -1]);

const userImageUpload$ = interval(2000).pipe(
  map((val) => imageStore.getValue().concat(val))
).subscribe(imageStore);

imageStore.pipe(switchMap(srcArray=>
 zip(interval(1000), from(srcArray)).pipe(
   map(([a, b]) => b),
   repeat()
  )
))

你可以这样尝试,你可以在我的stackblitz(角度示例)中看到同样的效果

private image:BehaviorSubject=新的BehaviorSubject([
-2,
-1
]);
private imagesChanged$=this.images.asObservable();
imageToDisplay$:可见;
恩戈尼尼特(){
this.imageToDisplay$=this.imagesChanged$.pipe(
开关映射(()=>间隔(1000)),
映射((v:number)=>v%this.images.value.length),
map((v:number)=>this.images.value[v])
);
}
addImage(){
这个,下一个([
…这个.images.value,
this.images.value[this.images.value.length-1]+1
]);
}

当前图像:{{imageToDisplay$| async}
添加图像

我将保留一个
currentImages$
可观测值,用于累计所有上传的图像,以及一个
currentImageIndex$
可观测值,用于保存当前应显示的图像索引。 然后,
liveImages
Observable(将两者结合起来)就是您想要的结果

const currentImages$ = userImageUpload$.pipe(
    scan((acc, curr) => [...acc, curr], [])
);

const currentImageIndex$ = interval(SLIDE_SHOW_INTERVAL).pipe(
    withLatestFrom(currentImages$),
    map(([, currImages]) => currImages),
    scan((accIndex, currImagesArr) => (accIndex + 1) % currImagesArr.length, 0)
);

const liveImages$ = currentImageIndex$.pipe(
    withLatestFrom(currentImages$),
    map(([currIndex, currImages]) => currImages[currIndex])
);

谢谢,很好地解决了这个问题。以前没有使用过扫描,但经过研究后,它看起来很棒。你确定它按预期工作吗?
<div>
    Current Image: {{ imageToDisplay$ | async }}
</div>

<button (click)="addImage()">Add a Image</button>
const currentImages$ = userImageUpload$.pipe(
    scan((acc, curr) => [...acc, curr], [])
);

const currentImageIndex$ = interval(SLIDE_SHOW_INTERVAL).pipe(
    withLatestFrom(currentImages$),
    map(([, currImages]) => currImages),
    scan((accIndex, currImagesArr) => (accIndex + 1) % currImagesArr.length, 0)
);

const liveImages$ = currentImageIndex$.pipe(
    withLatestFrom(currentImages$),
    map(([currIndex, currImages]) => currImages[currIndex])
);