Javascript 按顺序测试几个观察值

Javascript 按顺序测试几个观察值,javascript,angular,typescript,rxjs,Javascript,Angular,Typescript,Rxjs,我想做一些尝试和错误的方法。我有几个观测值,我想取第一个观测值的值,它没有出错。我尝试的是: const err1$ = throwError('err1'); const err2$ = throwError('err2'); const ok1$ = of('ok1').pipe(tap(x => console.log('hot ok1'))); const ok2$ = of('ok2').pipe(tap(x => console.log('hot ok2'))); con

我想做一些尝试和错误的方法。我有几个观测值,我想取第一个观测值的值,它没有出错。我尝试的是:

const err1$ = throwError('err1');
const err2$ = throwError('err2');
const ok1$ = of('ok1').pipe(tap(x => console.log('hot ok1')));
const ok2$ = of('ok2').pipe(tap(x => console.log('hot ok2')));
const ok3$ = of('ok3').pipe(tap(x => console.log('hot ok3')));

onErrorResumeNext(err1$, err2$, ok1$, ok2$, ok3$).pipe(
  first(),
  defaultIfEmpty('all failed'),
).subscribe(console.log);

我的问题是,我不想执行
ok2$
ok3$
,因为
ok1$
很好,但它们在这一过程中变得很热。我的目标是,我只在控制台日志中看到
hot ok1
(从点击)和
ok1
(从订阅)这就是你想要的,通过将每个可观察对象包装到一个管道中,该管道在出错时返回未定义(
catchDefaultConcat
)。之后,我们可以过滤掉任何错误的结果(如果
未定义的
是可观察的有效结果,则会有问题)

这是一个有趣的问题,
onErrorResumeNext
的文档说,它基本上只是连接源观测值和“吞咽”错误,但我也不确定为什么当你点击
first()
调用时它不取消订阅

const err1$=throwError('err1');
常量err2$=投掷者('err2');
const ok1$=of('ok1').pipe(tap(x=>console.log('hot ok1'));
const ok2$=of('ok2').pipe(tap(x=>console.log('hot ok2'));
const ok3$=of('ok3').pipe(tap(x=>console.log('hot ok3'));
const catchDefaultConcat=(…参数:可观察[])=>{
返回concat(args.map((arg)=>arg.pipe(
catchError(()=>of(未定义))
)));
}
catchDefaultConcat(err1$、err2$、ok1$、ok2$、ok3$).pipe(
concatAll(),
过滤器((val)=>val!==未定义),
第一个(),
catchError(()=>空),
defaultIfEmpty(“全部失败”),
).subscribe(console.log);

受埃维斯蒂费尔答案的启发,我现在找到了一种与

const err1$ = throwError('err1');
const err2$ = throwError('err2');
const ok1$ = of('ok1').pipe(tap(x => console.log('hot ok1')));
const ok2$ = of('ok2').pipe(tap(x => console.log('hot ok2')));
const ok3$ = of('ok3').pipe(tap(x => console.log('hot ok3')));

of(err1$, err2$, ok1$, ok2$, ok3$).pipe(
  map(obs$ => obs$.pipe(catchError(() => of(undefined)))),
  concatAll(),
  filter((val) => val !== undefined),
  first(),
  defaultIfEmpty('all failed'),
).subscribe(console.log);

在RxJs 6中,
onErrorResumeNext
方法对同步观测失败,但对异步观测有效。见:

在RxJs 7中,这是一种新方法,
onErrorResumeNext
方法适用于所有可观察对象。见:


onErrorResumeNext
目前正在使用,因此用
concat
catchError
替换可能是最好的选择


函数concatcatcatching(…args:observateInput

您的方法适用于异步观测值。因此您正在寻找一种同步执行此操作的方法?不,在我的实际案例中,这些是http调用,为最后一个管道打印错误
属性“pipe”在类型“OperatorFunction”上不存在。
您启发我找到一种工作方法,我将其作为另一种方法添加回答。它在Stackblitz上起作用了,我有一种感觉,尽管它可能不必要地复杂;)。您的版本更干净。请注意,在调用
defaultIfEmpty
之前,您仍然需要行
catchError(()=>EMPTY),
,否则它将永远不会被触发(如果过滤掉所有内容,它会抛出一个
EmptyError
)。我明白了,延迟(0)正在改变这里的行为。你能解释一下原因吗?@MoxxiManagarm据我所知,如果上一个源已完成,则直接订阅下一个源,而不检查目的地是否已关闭。从
源取消订阅(1)
仅在完成所有之前的同步操作后发生。
延迟(0)
将执行移动到下一个事件循环迭代,因此延迟取消订阅不是问题。此问题在RxJs 7 btw中已修复: