angular - 如何正确使用 Observable 和 Angular 异步管道?

标签 angular asynchronous rxjs observable

我尝试使用 Angular 异步管道,并使其能够显示我使用 http get 请求从服务器获取的时间。我有以下问题:

  • 如果我想再次重新执行 http get 请求以获取更新的数据,我在 testAsync() 中执行的操作是否正确,或者是否有更优雅的方法来执行此操作?
  • 我还注意到使用异步管道并重新请求数据时会出现一些闪烁。这在非异步版本(“testNormal()”)中不会发生。有什么办法可以防止这种情况发生吗?

Angular 分量:

    @Component({
      selector: 'app-async-test',
      templateUrl: './async-test.component.html',
      styleUrls: ['./async-test.component.scss']
    })
    export class AsyncTestComponent implements OnInit {
      private readonly baseApiUrl = environment.baseApiUrl;
      httpServerRequest$ = this.http.get<ServerTimeViewModel>(`${this.baseApiUrl}/admin/servertime`);
    
      testNormalResult: Date = null;
      testAsyncResult$: Observable<Date> = null;
      
      constructor(
        private http: HttpClient
      ) {}
    
      ngOnInit() {
          this.testAsync();
      }
    
      testNormal(): void {
        this.httpServerRequest$.subscribe(data => {
            this.testNormalResult = data.serverTime;
          });
      }
    
      testAsync(): void {   
        this.testAsyncResult$ = this.httpServerRequest$
          .map(d => d.serverTime);
      }
    }

ServerTimeViewModel 类:

    export class ServerTimeViewModel {
      serverTime: Date;
    }

模板:

    Test normal: {{ testNormalResult | date:'mediumTime'}}<br>
    Test async: {{ testAsyncResult$ | async | date:'mediumTime'}}<br>  
    <button type="button" (click)="testNormal()">test normal</button>
    <button type="button" (click)="testAsync()">test async</button>

最佳答案

答案在这里https://stackoverflow.com/a/41554338/54159对我帮助很大。解决方案是使用 ReplaySubject。现在,从网络服务刷新不会再导致任何闪烁。

我已将其全部放入数据服务中。我的组件直接绑定(bind)到 dataService.person$ 并调用 dataService.fetchRandomPerson(x) 来执行新的 http get 请求。

这是数据服务:

    @Injectable()
    export class DataService {
      private readonly baseApiUrl = 'https://swapi.co/api';
    
      private personSubject = new ReplaySubject<Person>(1);
      person$: Observable<Person> = this.personSubject.asObservable();
    
      constructor(
        private http: HttpClient
      ) { }
    
      fetchRandomPerson(personId: number): void {
        // re-execute http get
        // https://stackoverflow.com/a/41554338/54159
        this.http.get<Person>(`${this.baseApiUrl}/people/${personId}/`)
          .subscribe(res => this.personSubject.next(res));
        
        // note: no need to unsubscribe from http requests
        // https://stackoverflow.com/a/35043309/54159
      }
    }

这是一个运行版本: https://stackblitz.com/edit/angular-dpbe7t

关于angular - 如何正确使用 Observable 和 Angular 异步管道?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48687567/

相关文章:

c# - 如果异步调用不一定在不同的线程上执行,那么阻塞异步调用如何会导致死锁?

angular - 从 4/5 Angular JSON 后响应数据下载为 PDF

javascript - 找不到模块 '@firebase/app-types/private'

angular - 尝试从 Angular 应用程序连接到 asp.net core signalr hub 时出错

javascript - Angular 2,设置默认值以选择选项

c# - 无法在 Windows XP 计算机上安装/卸载 Async CTP

python-3.x - Python 3.6 异步 aioodbc 阻塞

angular - 三态复选框的支持字段被(重新)评估太频繁

Angular/RxJS - 有一个 RxJS 管道用于启动流吗?

Angular2 ngrx/store 多次登录尝试