javascript-从多个HTTP请求加载RxJs / Angular,并从每个请求更新模型

我已经使用Angular / RxJS已有几周了,并且具有根据多个REST请求构建的各种模型,到目前为止,我已经使用switchMap()实现了该模型.这是一个简单的示例(stackblitz:https://stackblitz.com/edit/angular-o1djbb):

import { Component,OnInit,} from '@angular/core';
import { Observable,of } from 'rxjs';
import { delay,switchMap } from 'rxjs/operators';

interface Order {
  id: string;
  itemName: string;
  details?: string;
}

@Component({
  selector: 'my-app',templateUrl: './app.component.html',styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  order: Order;

  ngOnInit() {
    this.getOrderFromApi(123)
      .subscribe(item => this.order = item);
  }

  getOrderFromApi(id): Observable<Order>  {
    const item$= this.getItemName(id);
    const fullItem$= item$.pipe(
      switchMap(n => {
        console.log(`Got name: '${n}''`);
        return this.getDetails(n);
      },(nameReq,detailsReq) => ({ id: '123',itemName: nameReq,details: detailsReq })
      ));
    return fullItem$;
  }

  getItemName(id): Observable<string> {
    return this.fakeXhr('foo');
  }

  getDetails(itemName): Observable<string> {
    console.log(`Got details '${itemName}''`)
    return this.fakeXhr('Some details about foo');
  }

  fakeXhr(payload: any) {
    return of(payload)
      .pipe(delay(2000));
  }
}

和一个简单的模板:

<p>
  item: {{order && order.itemName}}
</p>
<p>
  details: {{order && order.details}}
</p>

这可行,但是直到两个请求都完成,订单信息才会呈现.我想让itemName在可用时立即呈现,然后在可用时呈现细节.因此,利用了Observables可以发出的多个值.例如:

// first value emitted:
{ itemName: 'foo',details: null }
// second value emitted:
{ itemName: 'foo',details: 'Some details about foo' }

我意识到我可能可以通过BehaviourSubject或Redux来实现(就像我过去使用React一样),但是由于所有这些对我来说都是新事物,所以我觉得我没有一个简单的解决方案.

最佳答案
使用expand直接从第一个请求发出数据,然后执行第二个请求.

expand将递归调用内部请求,从上一个请求中获取订单作为输入,因此,我们仅在订单没有详细信息时才执行第二个请求,否则以EMPTY Observable结束递归.

import { Observable,EMPTY } from 'rxjs';
import { map,expand } from 'rxjs/operators';

getOrderFromApi(id): Observable<Order> {
  return this.getItemName(id).pipe(
    map(itemName => ({ id,itemName,details: null } as Order)),expand(order => order.details
      ? EMPTY
      : this.getDetails(order.itemName).pipe(
        map(details => ({ id,itemName: order.itemName,details } as Order))
      )
    )
  );
}

https://stackblitz.com/edit/angular-umqyem

返回的Observable将发出:

> {“ id”:123,“ itemName”:“ foo”,“ details”:null}
> {“ id”:123,“ details”:“有关foo的一些详细信息”}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


kindeditor4.x代码高亮功能默认使用的是prettify插件,prettify是Google提供的一款源代码语法高亮着色器,它提供一种简单的形式来着色HTML页面上的程序代码,实现方式如下: 首先在编辑器里面插入javascript代码: 确定后会在编辑器插入这样的代码: <pre
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代码高亮,因为SyntaxHighlighter的应用非常广泛,所以将kindeditor默认的prettify替换为SyntaxHighlighter代码高亮插件 上一篇“让kindeditor显示高亮代码”中已经
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高
JS对象如何转为json格式字符串
JS怎么获取图片原始宽高
怎么在click事件中调用多个js函数
js如何往数组中添加新元素
js如何拆分字符串
JS怎么对数组内元素进行求和
JS如何判断屏幕大小
js怎么解析json数据
js如何实时获取浏览器窗口大小
原生JS实现别踩白块小游戏(五)
原生JS实现别踩白块小游戏(一)