zoukankan      html  css  js  c++  java
  • [Angular RxJS] Single data observable pattern (combineLatest with startWith)

    For example we have multi API calls for one single page. 

    this.course$ = this.coursesService.loadCourseById(courseId)
    this.essons$ = this.coursesService.loadAllCourseLessons(courseId)

    This results multi <ng-container> in html:

      <ng-container *ngIf="(course$ | async) as data">
          <ng-container *ngIf="(lessons$ | async) as data">
            ...
          </ng-container>
       </ng-container>
     

    To avoid using multi ng-container, we can use single data observable pattern:

            const courseId = parseInt(this.route.snapshot.paramMap.get("courseId"));
    
            const course$ = this.coursesService.loadCourseById(courseId)
            const lessons$ = this.coursesService.loadAllCourseLessons(courseId)
    
            this.data$ = combineLatest([course$, lessons$])
                .pipe(
                    map(([course, lessons]) => {
                        return {
                            course,
                            lessons
                        }
                    }),
                    tap(console.log)
                );

    We use 'combineLatest' to merge two observable, and results in one single observable.

    But this brings one performance problem. Because 'combineLatest' need to wait both inner-obervables emit value then emits the final value. We end up wait all the data coming back from server. 

    Let's say, course$ should be resolved faster then lessons$, and we want to display the content related to coure$, then when the lessons$ data coming back, we display the content related to lesons$.

    To solve the problem, we can let both observable emit a init value, then when the data for inner-observable coming back, it will be merged one by one.

      ngOnInit() {
    
            const courseId = parseInt(this.route.snapshot.paramMap.get("courseId"));
    
            const course$ = this.coursesService.loadCourseById(courseId)
                .pipe(
                    startWith(null)
                );
    
            const lessons$ = this.coursesService.loadAllCourseLessons(courseId)
                .pipe(
                    startWith([])
                );
    
            this.data$ = combineLatest([course$, lessons$])
                .pipe(
                    map(([course, lessons]) => {
                        return {
                            course,
                            lessons
                        }
                    }),
                    tap(console.log)
                );
    
    
      }
      
    <ng-container *ngIf="(data$ | async) as data">
    
        <div class="course">
    
            <h2>{{data.course?.description}}</h2>
    
            <img class="course-thumbnail" [src]="data.course?.iconUrl" *ngIf="data.course">
    
            <table class="lessons-table mat-elevation-z7" *ngIf="data.lessons.length">
    
                <thead>
    
                <th>#</th>
                <th>Description</th>
                <th>Duration</th>
    
                </thead>
    
                <tr class="lesson-row" *ngFor="let lesson of data.lessons">
                    <td class="seqno-cell">{{lesson.seqNo}}</td>
                    <td class="description-cell">{{lesson.description}}</td>
                    <td class="duration-cell">{{lesson.duration}}</td>
                </tr>
    
            </table>
    
        </div>
    
    </ng-container>
  • 相关阅读:
    Working with WordprocessingML documents (Open XML SDK)
    How to Choose the Best Way to Pass Multiple Models in ASP.NET MVC
    Azure:Manage anonymous read access to containers and blobs
    Convert HTML to PDF with New Plugin
    location.replace() keeps the history under control
    On the nightmare that is JSON Dates. Plus, JSON.NET and ASP.NET Web API
    HTTP Modules versus ASP.NET MVC Action Filters
    解读ASP.NET 5 & MVC6系列(6):Middleware详解
    Content Negotiation in ASP.NET Web API
    Action Results in Web API 2
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12729393.html
Copyright © 2011-2022 走看看