【问题标题】:Angular 2 - Displaying async Object data from promiseAngular 2 - 显示来自承诺的异步对象数据
【发布时间】:2015-12-18 20:06:47
【问题描述】:

编辑:看起来我现在的主要问题是我似乎无法显示来自对象的异步数据。我有一个包含数据对象的承诺,当我使用时

{{ data | async }}

它会显示

[object Object]

问题是,我希望能够显示所有不同的属性;即名称、符号等。在 Angular 1 中,我只会使用

{{ data.Name | async }}

但这在这里不起作用,因为异步管道试图解析不存在的 data.Name 承诺。我想解决数据承诺,然后从中显示名称键。目前,我正在创建自己的管道以显示来自异步对象的键,但我想知道是否有内置的 Angular 2 管道或函数来处理这个问题!


我创建了一个 StockService 类,它返回一个包含对象的 Promise 到我的 StockInfo 类,其中包含要显示的 HTML。我想在我的 HTML 中显示该对象的名称,但似乎无法显示。

在我的 StockInfo 构造函数中:

this.stock.getStockData(this.ticker, http).then(function(val) {
  this.data = val;

  this.name = new Promise<string>(function(resolve) {
    resolve(this.data.Name);
  });
});

其中 this.stock 是 StockService 对象。

在我的 HTML 中:

<h2>{{name | async}}</h2>

在确定这一点之前,我尝试了许多不同的安排。我希望 StockService 类处理数据获取和 StockInfo 类处理显示。在 Angular 1 中,我会创建一个工厂来获取数据并处理控制器中的数据处理,但我不太确定如何在 Angular 2 中进行此操作。

有没有办法让它显示,或者有没有更好的方法来设计我应该研究的代码?谢谢!

【问题讨论】:

  • 您是否尝试过使用{{ (data | async).Name }}{{ (data | async)['Name'] }}
  • 你为什么要把this.name变成一个promise而不是写this.name = this.data.name?或者这只是一个人为的例子?
  • @Pylinux 我想这是一个人为的例子,允许minimal reproducible example

标签: asynchronous angular


【解决方案1】:

您不需要任何特殊的管道。 Angular 2 支持可选字段。你只需要添加?在你的对象中

{{ (data | async)?.name }}

{{(name | async)?}}

【讨论】:

  • 谢谢!我不知道这一点!
  • | async 是否适用于承诺?我以为它只适用于 Observables?
  • async pipe 接受 promise 或 observables。它在官方 Angular 2 文档中被提及。 angular.io/docs/ts/latest/guide/pipes.html
  • “安全导航运算符? 表示该字段是可选的,如果未定义,则应忽略表达式的其余部分”——来自angular.io/cheatsheet
【解决方案2】:

上面接受的answer 没有错。但是当我们需要显示对象的许多属性时,附加| async? 变得很麻烦。 更方便的解决方案如下:

<div *ngIf="data | async as localData">
   <div> {{ localData.name }} </div>
   <div> {{ localData.property1 }} </div>
   <div> {{ localData.property2 }} </div>
</div>

【讨论】:

  • 可以在没有*ngIf的条件行为的情况下做到这一点吗?
【解决方案3】:

你也可以从rxjs/observable 中使用pluck

{{ user.pluck("name") | async }}

Pluck 从 Observable 序列中的所有元素返回一个包含指定嵌套属性值的 Observable。如果一个属性不能被解析,它会为那个值返回 undefined。

【讨论】:

    【解决方案4】:

    如果你使用 Observable,你可以像这样显示数据:

    <div *ngIf="data | async; let _data">
       <h3>{{_data.name}}</h3>
    </div>
    

    <h3>{{(data | async).name}}</h3>
    

    【讨论】:

    • 请说明为什么这个标记解决了这个问题,应该如何使用它以及什么机制使它起作用。考虑链接一些文档。
    • 希望对你有帮助
    • smth 是什么意思?请在您的答案中选择真实的单词。
    【解决方案5】:

    我认为你把它弄得太复杂了,只需要做这样的事情。

    this.name = 
      this.stock.getStockData(this.ticker, http)
      .then( val => val.Name )
    

    <h2>{{name.Name | async}}</h2>
    

    【讨论】:

    • 谢谢!这无疑使事情变得简单了很多,我不敢相信我以前没想过这样写,但数据仍然没有显示在 HTML 中。我已经检查以确保 getStockData 返回带有正确数据的 Promise,但我仍然无法让它显示在 HTML 中。
    • 您确定getStockData 正在呼叫resolve
    • 是的;当我将 console.log 添加到我的 OP 中的怪物时,结果值包含我想要的所有数据。
    • 有趣的是,当我将 HTML 更改为

      {{name | async}}

      ,它会显示 [object Object],但尝试取消引用 Name 键会导致什么都不显示。
    • 谢谢西蒙!这可行,但这个对象中可能有 20 个键值对,我想在页面中显示所有 20 个。 getStockData 方法发出一个 HTTP GET 请求,我希望能够通过一次调用 getStockData 来获取所有这些数据。有没有办法将结果存储在对象中?
    【解决方案6】:

    所以我最终编写了自己的异步密钥管道。非常感谢 Simon 在这里帮助指导我。

    import {Pipe} from 'angular2/core';
    
    @Pipe({
        name: 'key',
        pure: false
    })
    
    export class KeyPipe {
        private fetchedPromise: Promise<Object>;
        private result: string;
    
        transform(value: Promise<Object>, args: string[]) {
            if(!this.fetchedPromise) {
                this.fetchedPromise = value
                    .then((obj) => this.result = obj[args[0]] );
            }
            return this.result;
        }
    }
    

    用法:

    <h2>{{ data | key: 'Name' }}</h2>
    

    如果 Angular 有自己的函数来解析异步对象的键,请评论一下。

    【讨论】:

      【解决方案7】:

      OP 要求承诺,但如果人们使用 Observables,则调整 @user2884505 的答案,因为 pluck 在最近版本的 RxJS 中不能直接在 observables 上作为一种方法使用,你可能会有这样的事情:

      import { Pipe, PipeTransform } from '@angular/core';
      
      import { Observable } from 'rxjs';
      import { pluck } from 'rxjs/operators';
      
      @Pipe({
        name: 'asyncKey',
        pure: false
      })
      export class AsyncKeyPipe implements PipeTransform {
        private observable: Observable<Object>;
        private result: Object;
      
        transform(value: any, ...args: any[]): any {
      
          if (!this.observable) {
            this.observable = value.pipe(pluck(...args));
            this.observable.subscribe(r => this.result = r);
          }
      
          return this.result;
        }
      }
      

      然后,您可以使用它,即使是嵌套键:

      {{ user$ | asyncKey: 'address' : 'street' }}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-01-22
        • 1970-01-01
        • 2021-03-25
        • 2017-04-17
        • 2021-02-04
        • 2020-06-10
        • 2016-11-17
        相关资源
        最近更新 更多