相关文章推荐
严肃的面包  ·  从零开始 - ...·  2 年前    · 
要出家的鞭炮  ·  pySpark | ...·  2 年前    · 
export class HttpRequestComponent { constructor ( private httpClient: HttpClient ) { } userList : any [] = []; //进行搜索 并且渲染到当前页面 search ( name : string ): void { this . sendSearchRequest (name) . subscribe ( res => { this . userList = res. items ; // 发送搜索请求 sendSearchRequest (name): Observable <{ items : any []}> { return this . httpClient . get <{ items : any []}>( 'https://api.github.com/search/users?' , { params : { q : name

以上代码足以完成需求,但是同时有以下几种隐患。

  • 请求效率比较低,如果我输出 netease 那么因为输入的变化, n , ne , net ... netease 会合计发起共7次请求。其实只要最后一次 netease 的结果。
  • 多次请求的结果响应时间并不可控,从而渲染结果不可控。假设第一条 n 的搜索请求响应耗时10s,而其他请求包含 netease 搜索都只需要1s,那页面最终的渲染结果为n的搜索结果,显然这样是不正确的。
  • 解决上述问题需要用到几个操作符:

    export class HttpRequestComponent implements OnInit {
      constructor(private httpClient: HttpClient) { }
      userList: any[] = [];
      // 搜索subject
      private onSearch$: Subject<string> = new Subject();
      search(name: string): void {
        // 每次输入都生产一个值
        this.onSearch$.next(name);
      private sendSearchRequest(name): Observable<{items: any[]}> {
        return this.httpClient.get<{items: any[]}>('https://api.github.com/search/users?', {
          params: {
            q: name
      ngOnInit(): void {
        // 初始化的时候订阅search$,更新页面搜索结果。
        this.onSearch$.asObservable()
          .pipe(
          	// 注意先后顺序
            // 防抖
            debounceTime(1000),
            // 变化才会请求
            distinctUntilChanged(),
            // 映射为新的Observable
            switchMap(name => this.sendSearchRequest(name))
          .subscribe(res => {
            this.userList = res.items;
    

    Subject 有着双重特性,它同时拥有 ObserverObservable 的行为。(多用于组件间通信场景)

    // 发送值
    subject.next( 2 )
    // 订阅值
    const subscription = subject.subscribe( (value) => console.log(value) )
    

    debounceTime前端常见的防抖策略,在一定时间内,只保留最后一次的值。

    ​ 当用户在1000ms内连续输入的时候,我们只针对最后一次输入做请求,大大提升了请求效率。

    distinctUntilChanged只有值发生变化才会更新。只有内容变化才会触发请求。

    ​ 部分浏览器输入中文可能会产生输入值不变,但是重复触发输入事件的问题

    switchMap 有点类似于Promise。实际作用为完成前一个observable,映射成一个新的observable。

    ​ 实际在angular中,当在上述的重复请求业务场景中,例如搜索,翻页等等,当前一条请求未完成,而后一条请求已经发出,那么此操作符会导致前一条请求被取消,从而保证了请求以及结果的顺序。