1. forkJoin

  • 当所有 observables 完成时,发出每个 observable 的最新值。
  • 如果内部 observable 不完成的话,forkJoin 永远不会发出值!
  • 多个 observables 按发出顺序相对应的值的组合,试试 zip
  • 关心每个 observable 最后发出的值时,此操作符是最适合的
  1. getForkJoin() {
  2. // 注:上传excl的时候返回类型为Observable<unknown[]>,
  3. // 此时类型不对无法进行pipe和subscribe操作,
  4. // 解决: 重新给定类型为需要的类型或者any
  5. return ForkJoin('发送的Observable') as Observable<any>;
  6. }

2. catchError(w3c很详细)

一个以参数为参数的函数 err,这是错误(捕获此错误将终止监听);而 caught,其中 是可观察的源, 再次返回来“重试”该可观察的源(当前发送出来的源,链式)。 无论观察到什么 将返回, selector将用于继续可观察的链(执行完终止监听)。

  1. https://blog.csdn.net/weixin_28762271/article/details/112650086
  • 成功处理函数 next,每次流发出值时调用该函数
  • 错误处理函数 error,只有在发生错误时才调用该函数,此处理函数本身接收一个错误
  • 完成处理函数 complete,仅当流完成时才调用该函数 ```typescript // Observable的契约定义:任何给定的流只能出错一次 // 捕获之后采用替换策略(本身也可能出现错误),可继续,下面代码第二个捕获发出回退值 // 捕获后在抛出捕获的错误,throwError(),下面第一个捕获 // 可以使用多个捕获,在链的每个点采用不同的错误策略

async validReelNo(snList: string[]): Promise { const { workOrder } = this.validateGrForm.value; this.inputs.toArray()[2].select();

return new Promise((resolve, reject) => { this.dipDropBoardSrv.getSingleSn({ workOrder, snList }).pipe( timeoutWith(3000, throwError(‘验证sn,请求超时’)), catchError(e => { // 监听pass和fail this.dipDropBoardSrv.setSub(false);

    // 记录错误日志
    const currTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
    const str = e?.error?.error?.message ?? e ?? '条码校正失败';
    const msg = {
      tit: `[${currTime}]${str}`,
      ind: 1
    };
    this.dipDropBoardSrv.setjouSub([msg]);
    throw new Error('校验' + e.toString());
  }),
  catchError((e, caught) => {
    return [];
  }),
  map(snVal => snList)
).subscribe(res => {
  resolve(res);
}, err => {
  reject(err);
});

});

}

<a name="Ymorw"></a>
### 3. 优雅销毁监听

1.  常规销毁:subscribe会返回一个**Subscription** 对象, 调用unsubscribe()方法;
1. 优雅销毁:使用**takeUntil** 操作符代替**unsubscribe**
```typescript
// 存在的问题:takeUntil()放前面,在后续流中还是会继续执行完毕
destroy$ = new Subject();

this.reelNoSubject.asObservable().pipe(
  takeUntil(this.destroy$),
  skipWhile(snArr => snArr.length === 0),
  switchMap(snArr => this.validReelNo(snArr))
).subscribe(data => {
  console.log(data);
  this.posttadd(data);
  // data.subscribe(a => {
  //     this.posttadd(a);
  // });
}, err => {
  console.log('reelNoSubject  subscribe e ', err);
});

ngOnDestroy() {
   this.destroy$.next();
   this.destroy$.complete();
 }


// 类似这样
// ...
this.stream$
  .pipe(
    takeUntil(this.compelete$),
    switchMap(id => 
      combineLatest(
        this.store.pipe(select(getAuth, { id, name: 'create' })),
        this.store.pipe(select(getAuth, { id, name: 'edit' })),
        this.service.getWhiteList()
      )
    ),
  )
  .subscribe(([res1,  res2, res3]) => {
     // ...
   });
// ...

image.png