Angular 如何将多笔资料上传後,取得全部回传资料,再送到另一支 API

来回顾一下前几天的日记文

Angular 图片上传之...日记文
程序码流程规划之...日记文

与今天介绍的内容有关,如何将多笔资料上传後,取得全部回传资料後
再将其资料整理,送到另一支 API
这次将会使用 RxJS 来做处理

情境

我有一笔订单,里面有许多的产品,需要先将产品上传後,取得产品回传後的 id,再将这些 id 塞到这笔订单里,此笔订单才算完成。

状况

因为是打 API,所以会有不同步的问题产生,首先必需要先克服这一点,才能继续下一步


实作

假资料 API FakeStoreAPI

在 service 里先建立两支 post api
一支是 createProd 用来建立产品资料
另一搬是 createOrder 用来建立订单资料

service.ts

createProd(data: any): Observable<any> {
  const url = `https://fakestoreapi.com/products`;
  const newData = JSON.stringify(data);
  return this.httpClient.post(url, newData, {
    headers: new HttpHeaders({
      'Content-Type': 'application/json',
    }),
  });
}

createOrder(data: any): Observable<any> {
  const url = `https://fakestoreapi.com/carts`;
  const newData = JSON.stringify(data);
  return this.httpClient.post(url, newData, {
    headers: new HttpHeaders({
      'Content-Type': 'application/json',
    }),
  });
}

在 template 里做一个 submit 的按钮

<button (click)="onSubmit()">Create Product In Order</button>

模拟预设传入资料
.ts

products = [
  {
    title: 101,
    price: "11",
    quantity: 1,
  },
  {
    title: 102,
    price: "22",
    quantity: 35,
  },
  {
    title: 103,
    price: "33",
    quantity: 10,
  },
];

order = {
  userId: 5,
  date: new Date().toJSON(),
};

重头戏来罗!!

.ts

onSubmit(): void {
  const maydata = {
    products: this.products,
    order: this.order,
  };

  of(maydata)
    .pipe(
      concatMap((data) => {
        const update$ = data.products.map((product) => {
          return this.appService.createProd(product).pipe(
            map((res) => {
              return {
                productId: res._id,
                quantity: product.quantity,
              };
            })
          );
        });
        return combineLatest(update$ as Array<Observable<any>>).pipe(
          map((d) => {
            const combineData = { ...data.order, products: d };
            return combineData;
          })
        );
      }),
      switchMap((data) => {
        return this.appService.createOrder(data);
      })
    )
    .subscribe();
}

如图所示:


案例解说 (RxJs 连续技使用)

这里我先将所有要传入的资料包成一个物件,然後使用 rxjs 里的 concatMap (注一)去处理产品上传这部份,
concatMap 的特性就是等所有资料都回传回来後,才会进行下一步动作,接着再使用 combineLatest(注二) 的特性处理回传回来後的资料,再使用 switchMap(注一),打一下笔 API

说起来简单 但实际上若是不熟 RxJs 会卡蛮久的 (没错,我就是苦主之一 XDDD)


附录

范例:https://stackblitz.com/edit/angular-ivy-qiwggq

注一:RxJS 转换类型 Operators (2) - switchMap / concatMap / mergeMap / exhaustMap
注二:RxJS 组合/建立类型 Operators (2) - combineLatest / forkJoin / race


<<:  Ruby on Rails CSRF 攻击是什麽?

>>:  [第07天]理财达人Mx. Ada-删单作业

自动化测试,让你上班拥有一杯咖啡的时间 | Day 2 - Cypress 环境设定

此系列文章会同步发文到个人部落格,有兴趣的读者可以前往观看喔。 今天要教大家 Cypress 环境...

让按钮来个酷动态! 操纵DOM事件:CSS 篇 (二)

在:hover、:active的CSS设定中,当然也可以加上animation,当事件触发时开始播放...

Day27_是不是跟个资法卯上了~哈哈~CBPR-2021/10/10

想说CBPR是什麽? 与GDPR不同的是,CBPR并非是一套要求所有国家遵循的规范, 而更像是一种参...

DAY18 Conponent Tree 的黄色警告三角型?!

乳提,没错就是这样, 「为甚麽...」女同学正被这个问题所困扰着。 「别担心,我来了(歪头拉裤头拨头...

Day18 Elastic APM (二)

接下来我们要开始运用APM Agent的函式库来去做应用程序方面的监控。 APM 安装 kibana...