Rxjs 错误后仅触发一次订阅

Rxjs 错误后仅触发一次订阅,rxjs,Rxjs,我是rxjs的新手,我正试图弄清楚下面的代码中发生了什么 事实上,为了说明这个想法,我准备了两个简单的承诺(resolvePromise和rejectPromise),一个解决承诺,另一个拒绝。 “Subject”实例用于触发这两个承诺(通过mergeMap和forkJoin管道)。最后,添加了两条单独的指令(source$.next('xxx'),希望触发订阅两次 但最后,只有第一个“source$.next('1')”触发订阅,而下一个“source$.next('2')”似乎什么也不做 我

我是rxjs的新手,我正试图弄清楚下面的代码中发生了什么

事实上,为了说明这个想法,我准备了两个简单的承诺(resolvePromise和rejectPromise),一个解决承诺,另一个拒绝。 “Subject”实例用于触发这两个承诺(通过mergeMap和forkJoin管道)。最后,添加了两条单独的指令(source$.next('xxx'),希望触发订阅两次

但最后,只有第一个“source$.next('1')”触发订阅,而下一个“source$.next('2')”似乎什么也不做

我猜这种行为是由拒绝承诺造成的,它字面上是“抛出异常”。 但是我想知道如何修复这段代码,这样第二个“source$.next('2')”也会触发订阅

非常感谢

import { of,forkJoin,Subject } from 'rxjs';
import { mergeMap } from 'rxjs/operators';

const resolvePromise = val =>
  new Promise(resolve => resolve(`resolve value: ${val}`));

const rejectPromise = err =>
  Promise.reject(`reject error: ${err}`);

const source$ = new Subject();

source$
  .pipe(mergeMap(val => {
    return forkJoin([
      resolvePromise(val), 
      rejectPromise(val)
      ]);
  }))
  .subscribe(
     console.log, 
     console.error
  );

  source$.next('1');
  source$.next('2');

更新 根据Andrei Gătej在下面给出的建议,为了克服这个问题,我选择在forkJoin之后使用catchError管道,并将错误处理放在内部

source$.pipe(
  mergeMap(val => {
    return forkJoin([
      resolvePromise(val),
      rejectPromise(val)
    ])
      .pipe(
        catchError(err => {
          // your error handling business logic
          console.error(err);
          return empty();
        })
      );
  }))
  .subscribe(console.log);
拒绝承诺,字面意思是“抛出一个例外”

从RxJS内部处理承诺的方式来看,我认为你是对的:

promise.then(
(值)=>{
如果(!subscriber.closed){
订户。下一个(值);
subscriber.complete();
}
},
(err:any)=>subscriber.error(err)/!
)

同样值得一提的是,正如您从上面的代码片段中看到的,一旦承诺第一次得到解决,解决值
完成
通知将被传递

complete
部分对于
forkJoin
操作员非常重要

forkJoin
订阅所有提供的可观察对象,并等待直到所有操作完成。只有当观测值至少发射一次时,它才会发送一个值为的数组

当一个被观察者发出一个
错误
通知时,
forkJoin
将立即在链的更远处发送该
错误
通知


以下是我的方法:

source$
.pipe(合并映射(val=>{
返回叉连接([
承诺(val),
from(拒绝承诺(val)).pipe(catchError(err=>of(err)))
]);
}))
.订阅(
console.log,
控制台错误
);

我们使用的是来自的
,这样我们可以尽早截获承诺错误,这允许我们使用
捕获错误
并使用一个可观察的对象,该对象将发送一个值,然后
完成
通知(
of(err)
)。

您需要通过
重试
重复
重新订阅

从'rxjs'导入{of,forkJoin,Subject};
从“rxjs/operators”导入{mergeMap};
const resolvePromise=val=>
新承诺(resolve=>resolve(`resolve value:${val}`));
常量拒绝承诺=错误=>
Promise.reject(`reject error:${err}`);
const source$=新主题();
source$.pipe(
合并映射(val=>forkJoin([
承诺(val),
拒绝承诺(val)
])),
catchError(()=>空),
重复(),
).订阅(
console.log,
控制台错误
);
来源$.next('1');
来源$.next('2');

嗨,安德烈,谢谢你的建议。你的建议对我来说确实有效。根据您的想法,我想知道它是否也可以作为这样做的解决方案:(对不起注释中的代码样式)source$.pipe(mergeMap(val=>{returnforkjoin([resolvespromise(val),rejectPromise(val)]).pipe(catchError(err=>{console.error(err);returnempty()};})订阅(console.log);我的意思是,我们将错误处理放在forkJoin之后的catchError函数中。这样我们就不需要签入订阅,无论我们是否得到错误或正常结果。如果source$是主题和/或只要未完成,我认为这应该可以正常工作。嗨,satanTime,谢谢你的建议。“重试”会多次尝试解决forkJoin问题,但是,如果其中一个承诺/可观察项始终失败,例如,业务规则检查失败,那么无论我们重试多少次,结果都将保持不变。啊哈,我明白了,您的代码中是否使用了
主题
?我已将示例更新为使用
repeat