Angular 6如何异步更新列表信息?

发布于 2022-09-07 16:12:06 字数 4342 浏览 40 评论 0

本人前端萌新,学习过一点点Angular,然后自己写了一个简单例子,就是显示一下浏览器信息,相关代码如下,可以正常运行,界面会先显示浏览器的信息,然后过几秒显示出IP地址。

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import platform from 'platform';
import 'rxjs/add/operator/toPromise';

@Injectable()
export class ClientInfoService {
  private static ipUrl = 'http://httpbin.org/ip';

  constructor(private httpClient: HttpClient) {

  }

  getClientInfo(): Promise<ClientInfo[]> {
    return new Promise((resolve, reject) => {
      const clientInfo: ClientInfo[] = [];
      clientInfo.push({key: '操作系统', value: `${platform.os}`});
      clientInfo.push({key: '浏览器', value: `${platform.name} ${platform.version}`});
      clientInfo.push({key: '用户代理', value: platform.ua});
      this.httpClient.get(ClientInfoService.ipUrl)
        .subscribe(data => {
          clientInfo.push({key: 'IP地址', value: data['origin']});
          resolve(clientInfo);
        }, err => {
          reject(err);
        });
    });
  }
}

export interface ClientInfo {
  key: string;
  value: string;
}

然后Angular更新到6了,我研究一段时间以后,尝试升级了一下,好不容易代码能运行了,但是这下IP地址无法更新了。代码现在如下,程序其他部分也作了相应修改,可以编译。但是现在程序可以显示浏览器的信息,IP地址永远为空。我想了想,感觉问题应该是出在rxjs这里,因为我对这些概念不太理解,代码肯定写错了,所以希望高手们给我解解惑。感谢各位!

@Injectable()
export class ClientInfoService {
  private static ipUrl = 'http://httpbin.org/ip';

  constructor(private httpClient: HttpClient) {

  }

  getClientInfo(): Observable<ClientInfo[]> {
    const clientInfo: ClientInfo[] = [];
    clientInfo.push({key: '操作系统', value: `${platform.os}`});
    clientInfo.push({key: '浏览器', value: `${platform.name} ${platform.version}`});
    clientInfo.push({key: '用户代理', value: platform.ua});
    const data = this.httpClient.get(ClientInfoService.ipUrl)
      .pipe(
        catchError(this.handleError('获取IP地址', '网络错误'))
      );
    clientInfo.push({key: 'IP地址', value: data['origin']});
    return of(clientInfo);
  }

  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
      console.error(error);
      return of(result as T);
    };
  }
}

export interface ClientInfo {
  key: string;
  value: string;
}

感谢各位的解答,现在终于可以显示IP地址了,但是还有一个问题就是原来是立即显示一些东西,然后获取到IP地址之后才更新。现在我这个代码变成了需要等到IP地址拿到之后才整个显示数据。请问这下应该如何处理?

  getClientInfo(): Observable<ClientInfo[]> {
    const clientInfo: ClientInfo[] = [];
    clientInfo.push({key: '操作系统', value: `${platform.os}`});
    clientInfo.push({key: '浏览器', value: `${platform.name} ${platform.version}`});
    clientInfo.push({key: '用户代理', value: platform.ua});
    return this.httpClient.get(ClientInfoService.ipUrl)
      .pipe(
        map(data => data['origin']),
        catchError(this.handleError('获取IP地址', '网络错误')),
        map(e => {
          clientInfo.push({key: 'IP地址', value: e});
          return clientInfo;
        })
      );
  }

感觉我描述的不够清晰,顺便补上视图显示的代码。

@Component({
  template: `
    <mat-table #table [dataSource]="dataSource">
      <ng-container matColumnDef="key">
        <mat-header-cell *matHeaderCellDef>项目</mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.key}}</mat-cell>
      </ng-container>
      <ng-container matColumnDef="value">
        <mat-header-cell *matHeaderCellDef>值</mat-header-cell>
        <mat-cell *matCellDef="let row"> {{row.value}}</mat-cell>
      </ng-container>
      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
    </mat-table>
  `,
})
export class ClientInfoComponent implements OnInit {
  dataSource: ClientInfoDataSource;
  displayedColumns = ['key', 'value'];

  constructor(private clientInfoService: ClientInfoService) {
  }


  ngOnInit(): void {
    this.dataSource = new ClientInfoDataSource(this.clientInfoService);
  }
}

class ClientInfoDataSource implements DataSource<any> {
  constructor(private clientInfoService: ClientInfoService) {
  }

  connect(): Observable<ClientInfo[]> {
    return this.clientInfoService.getClientInfo();
  }

  disconnect(): void {
  }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

江湖彼岸 2022-09-14 16:12:06

rxjs 需要订阅,而上面这段代码中 this.httpClient.get并未subscribe,也就不会触发,或者即使订阅了也因为是异步执行而没有效果,最终直接返回了值为clientInfo的observer,这个值始终都会是[]
正确做法getClientInfo()应该返回代码中定义的data这个Observable,比如说:

getClientInfo(): Observable<ClientInfo[]> {
    ...
    const data = this.httpClient.get(ClientInfoService.ipUrl)
      .pipe(
        map((rs) => [{key: 'IP地址', value: rs['origin']}]),
        catchError(this.handleError('获取IP地址', '网络错误'))
      );
    return data;
  }
野心澎湃 2022-09-14 16:12:06

好好看官方文档老铁

getConfig() {
  return this.http.get(this.configUrl);
}

showConfig() {
     this.configService.getConfig()
    .subscribe((data: Config) => this.config = {
        heroesUrl: data['heroesUrl'],
        textfile:  data['textfile']
    });
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文