在模板中使用异步管道可观察到的不适用于单个值

     2023-02-23     298

关键词:

【中文标题】在模板中使用异步管道可观察到的不适用于单个值【英文标题】:Observable with Async Pipe in template is not working for single value 【发布时间】:2017-01-10 20:07:23 【问题描述】:

我有一个组件向我的服务请求 Observable 对象(即底层的 http.get 返回一个对象)。

对象(一个可观察对象)在我的模板中与异步管道一起使用。 不幸的是,我收到一个错误:

无法读取 null 的属性“姓氏”

我一直在为这个问题头疼。类似类型的代码可以在对象列表上正常工作(与 *ngFor 一起使用)。

<li>(person | async)?.lastname</li>

我的服务方法:

getPerson(id: string): Observable<Person>         
   let url = this.personsUrl + "/" + id;
   return this.http.get(url, headers: new Headers('Accept':'application/json'))
              .map(r => r.json())
              .catch(this.handleError); //error handler

在我的组件中:

//... imports omitted

@Component(
  moduleId: module.id,
  selector: 'app-details-person',
  templateUrl: 'details-person.component.html',
  styleUrls: ['details-person.component.css'],
)
export class DetailsPersonComponent implements OnInit, OnDestroy 

   person: Observable<Person>;
   sub: Subscription;

   constructor(private personService: PersonService, private route: ActivatedRoute) 
   

  ngOnInit() 
     this.sub = this.route.params.subscribe(params => 
                 let persId = params['id'];
                 this.person = this.personService.getPerson(persId);
                );
  

  ngOnDestroy(): void 
     this.sub.unsubscribe();
  


显然,可观察对象是/返回管道中的空对象值。 我已经检查了我是否真的从我的服务中获得了一个非空的 Observable,并且我可以确认存在从我的服务返回的(基础)对象。

当然,在从服务中检索 Observable 后,我可以在我的组件中订阅 observable,但我真的很想使用异步构造。

顺便说一句,另一个问题:是否已经有关于如何处理异步管道中发生的错误的模式? (使用异步管道的一个缺点......错误会延迟到视图的渲染时间。

【问题讨论】:

这应该可以。请显示返回 observable 的服务代码,以及定义 person 的组件代码。或者更好的是,创建一个plunker。 嗨,马克,我已经更新了上面的问题部分。您可以阅读上面的服务片段和组件代码。谢谢。 【参考方案1】:

第一次渲染视图时,person 未定义,因为该组件属性仅在路由参数订阅触发时异步创建。您最初需要创建一个空的 observable。而不是

person:Observable<Person>;

试试

person = Observable.of<Person>(Person());  // or however you create an empty person object
    // the empty object probably needs a lastname field set to '' or null

我通常通过

处理服务中的错误
    返回一个空的可观察对象 将错误报告给某些应用程序范围的(单例)服务。然后某些(单一)组件会在页面某处显示这些错误(如果适用)。

【讨论】:

嗨,马克,感谢您的回复。事实上,我同意关于人员和路由参数代码的异步行为。我听从了你的建议,但我仍然看到同样的错误。似乎视图是在定义人员之前呈现的(使用服务调用)。我是否处于错误的生命周期? 如果person = Observable.of&lt;Person&gt;(Person()); is defined before your constructor, it should exist when the view is first rendered. You can test this by commenting out your this.person = ...`代码。 嗨,马克,(之前)做过,但徒劳无功。这是一个大脑破坏者:-(我开始考虑我是否在库和兼容性方面存在问题。正如你之前所说......这应该有效。直截了当但仍然是一个问题。【参考方案2】:

请尝试换行

person:Observable< Person>

进入

person:Observable< any>;

如果这不起作用,请打印出这个 person | async | json ,当然请使用上面的更改,看看你会得到什么。

【讨论】:

你试过 flatMap 而不是 map 吗?【参考方案3】:

您无需订阅ngOnInit 中可观察到的路由数据。

您可以将路由数据与 personService 可观察对象链接在一起,形成一个新的可观察对象,而不是在每次发出路由数据 observable 时都订阅和创建一个全新的 observable。这就是函数式编程的精髓:

函数式反应式编程的本质是指定 声明时值的动态行为。

考虑到这一点,您可以在声明时声明关于“人”的所有内容:

person: Observable<Person> = this.route.params.pipe(
  map(params => params.id),
  mergeMap(persId => this.personService.getPerson(persId)),
);

这样做有很多好处:

直到有东西订阅它(如异步管道),observable 才会真正触发。这意味着除非您在模板中使用异步管道,否则它不会向该人发出请求。 您不需要处理取消订阅。异步管道将为您完成这项工作。 通过查看代码很容易看出是什么构成了“Person”。这一切都在一个地方定义。 您不需要创建一个空的初始化 observable,它可能不是一个有效的“Person”。

话虽如此,异步管道仍然可以默认为 null,您可以在模板中使用 ngIf 处理它:

 <li *ngIf="(person | async) as person">person.lastname</li>

【讨论】:

这应该是公认的答案。它避免了创建一个空的人对象,当有正确的方法时,它被用作一种变通方法,并避免了不必要的订阅。【参考方案4】:

如果您使用 Subject&lt;T&gt; observable 而不是 ReplaySubject&lt;T&gt;BehaviorSubject&lt;T&gt;,则可能会发生这种情况。

Subject&lt;T&gt; 发生的情况是,它只向当时注册的任何听众“广播”一次其值。

因此,如果您在可观察的message: Subject&lt;string&gt; 上调用next('hello word'),它只能在那个“部分”UI 存在的情况下及时更新UI。

所以在这个例子中消息不会出现 - 除非你调用next 两次!

<div *ngIf="message | async">
   here is the message  message | async 
</div>

最简单的解决方案是使用ReplaySubject&lt;string&gt;(1),其中1 是它记住的值的数量(我们这里只需要一个)。

【讨论】:

Ionic 4 Angular模板与异步管道绑定到可观察

】Ionic4Angular模板与异步管道绑定到可观察【英文标题】:Ionic4Angulartemplatebindingwithasyncpipetoobservable【发布时间】:2018-11-1903:23:54【问题描述】:我正在将旧的ionic应用程序从V2移动到V4-alpha,并且无法使用异步管道在模板中绑定到... 查看详情

与模板中的异步管道组合以观察值变化时,管道运算符不起作用

】与模板中的异步管道组合以观察值变化时,管道运算符不起作用【英文标题】:Pipeoperatornotworkingwhencombiningwithasyncpipeintemplateforvaluechangesobservable【发布时间】:2019-10-0514:20:29【问题描述】:我正在尝试捕获用户输入并根据输入... 查看详情

如何使用来自html的异步管道获取可观察对象的嵌套值

】如何使用来自html的异步管道获取可观察对象的嵌套值【英文标题】:Howtogetnestedvaluesofanobservableusingasyncpipefromhtml【发布时间】:2021-03-0222:37:30【问题描述】:我在Angular中有一些html块,我想用一些可观察对象的嵌套值来填写,... 查看详情

Angular/Rxjs 管道异步不适用于 s-s-r?

...无限循环(似乎服务器正在等待解析observable)。我正在使用:@nestjs/ng-universal角9火力基地Rxjs这样一个简单的例子可以工作:<p 查看详情

在单个 MySQL 查询中使用多个临时表(适用于 phpMyAdmin,但不适用于 PHP)

】在单个MySQL查询中使用多个临时表(适用于phpMyAdmin,但不适用于PHP)【英文标题】:UsingmultipletemporarytablesinasingleMySQLquery(worksinphpMyAdmin,butnotPHP)【发布时间】:2014-03-2109:28:36【问题描述】:我想避免使用真实表格作为解决方法... 查看详情

使用表数据中可观察到的剔除值来应用 CSS 类

】使用表数据中可观察到的剔除值来应用CSS类【英文标题】:UsevalueofknockoutobservablewithintabledatatoapplyCSSclass【发布时间】:2021-01-1823:22:06【问题描述】:我正在努力让KOCSSbinding工作。portAvailable是$root.devices中每个设备中存在的可观... 查看详情

可观察管道中的异常被抑制

...servable定期发出值,直到另一个observable发出。所以我可以使用timer和takeUntil来实现这一点。但是然后我想处理每个发出的值并在某些条件变为真时停止(错误)发出。所以我写下一段代码:consttimer,Subject=\ 查看详情

使用http模块时出错-检测到的asp.net设置不适用于集成管理管道模式(代码片段)

启动应用程序时出错。AnASP.NETsettinghasbeendetectedthatdoesnotapplyinIntegratedmanagedpipelinemode.我创建了一个HTTP模块,它从请求头读取信息并将数据写入cookie。这是代码。namespaceMy.WebpublicclassUserIdModule:IHttpModuleprivateHttpApplicat 查看详情

在模板中使用带有异步管道的 Observable 时显示加载

】在模板中使用带有异步管道的Observable时显示加载【英文标题】:DisplayloadingwhileusingObservablewithAsyncpipeintemplate【发布时间】:2017-02-1223:41:30【问题描述】:情况:我正在使用FirebaseObjectObservable来填充我的Ionic2(rc0)模板。模板代码... 查看详情

rxjs-连接并合并两个可观察对象(代码片段)

...jobs$=this.jobSandbox.observeJobsAfterFiltering()我用它作为带有Input管道的Angular组件的async值。我想在单个对象中转换这两个可观察对象并将它们的值“合并”在单个对 查看详情

管道操作符时如何返回可观察到的`forkJoin`

】管道操作符时如何返回可观察到的`forkJoin`【英文标题】:Howtoreturna`forkJoin`observablewhenpipingtheoperators【发布时间】:2018-11-0714:06:25【问题描述】:在我拥有这个运行良好的解析器之前:resolve()returnforkJoin(this.getData1(),this.getData2(),... 查看详情

使用角度异步管道以完全反应式方式刷新数据

...过mergeMap等管道的复杂而复杂的解决方案。我正在组件HTML模板中从命令式HTTP可观察方法(手动订阅)转变为 查看详情

java示例代码_避免在可观察到的事件通知中使用if/else

java示例代码_避免在可观察到的事件通知中使用if/else 查看详情

使用异步管道显示从应用程序状态检索到的 Observable 数据

】使用异步管道显示从应用程序状态检索到的Observable数据【英文标题】:UseasyncpipetoshowObservabledataretrievedfromtheApplicationState【发布时间】:2021-08-2301:17:51【问题描述】:我的代码从ApplicationState获取数据,然后在component.html中显示... 查看详情

如何在角度 http 拦截器中抛出可观察到的错误

】如何在角度http拦截器中抛出可观察到的错误【英文标题】:howtothrowobservableerrorinangularhttpinterceptor【发布时间】:2018-10-1507:57:01【问题描述】:我试图在拦截器中抛出一个可观察到的错误,然后处理这个错误。但我不能。当succ... 查看详情

无法在网络调用中返回可观察到的 customError

...tworkcall【发布时间】:2018-10-1511:16:54【问题描述】:我想使用catchError将我的错误恢复为自定义类型。起初,我希望我的网络层返回Observable,然后在ViewModel中订阅了.OnNext、.OnError、.OnCompleted事件,但我不知道应 查看详情

suppressWarnings() 不适用于管道运算符

...【发布时间】:2018-02-2415:34:04【问题描述】:我正在尝试使用suppressWarnings()函数来抑制警告。令人惊讶的是,它在正常使用时会删除警告,但在使用管道%&gt;%运算符时却无法这样做。这是一些示例代码:library(magrittr)c 查看详情

异步验证器不适用于 Angular 中的模板驱动表单

】异步验证器不适用于Angular中的模板驱动表单【英文标题】:AsyncValidatornotworkingwithTemplatedrivenFormsinAngular【发布时间】:2017-10-1801:31:52【问题描述】:我为我的模板驱动表单创建了一个异步验证器。importDirective,forwardReffrom"@angular... 查看详情