【问题标题】:asynsPipe produces null as a first valueasyncsPipe 产生 null 作为第一个值
【发布时间】:2019-12-09 21:10:46
【问题描述】:

当在 Angular 中使用不立即触发事件的异步管道时(http 请求或任何可观察到的延迟),第一个值为 null 为什么会这样?如何避免?

<hello [data]="delayedData$|async"> </hello>

第一个变化:

SimpleChange {
   currentValue: null
   firstChange: true
   previousValue: undefined
}

第二次改变:

SimpleChange {
   currentValue: 'some real data'
   firstChange: false
   previousValue: null
}

stackblitz 示例: https://stackblitz.com/edit/http-async-pipe-crxm32

【问题讨论】:

  • async管道的实现来看,这不是预期的行为吗?
  • 你可以简单地使用'startWith'运算符,就像你在你的observable中使用的那样,结果实际上是合乎逻辑的,因为observable不包含任何初始值,它打印null,试试operator startWith ,或者它是@Muhammed Albarmavi 在这里写下的变体(我建议使用 startwith),我知道您在现实生活中的代码中可能有很多复杂的数据结构,但是您也可以传递空数组空对象等
  • 如果你深入研究实现——你可以期待它,但在官方 dos 中没有任何内容,恕我直言,这是非常奇怪的行为——我只期望我的 observable 中的值,没有副作用跨度>

标签: angular rxjs async-pipe


【解决方案1】:

这是预期的行为。为避免这种情况,您可以使用 *ngIf 指令:

<hello *ngIf="delayedData$|async as delayedData" [data]="delayedData"> </hello>

这只会在delayedData$ 发出值时呈现hello 组件。

Angular docs on ngIf

【讨论】:

  • 这是一个不错的解决方案,但问题不是仅在数据到来时才渲染元素,而是要确保我输入的内容是我从后端获得的数据。
  • @KaterinaPavlenko but the problem is not to render element only when data comes?我不明白那个说法。你能澄清一下你的意思吗?
  • 您的解决方案让我仅在延迟数据$ 产生非空值时渲染组件。这很好,但是如果delayedData$ 可以 产生空值并且这是它的正常行为呢?而且我想渲染组件不依赖于延迟数据$产生的值?
  • 长话短说——我想在 ngOnChanges() 中使用 @Input 数据并将 default null 与真正的 null 分开
【解决方案2】:

试试这样:

<ng-container *ngIf="delayedData$ | async; let item">
  <hello name="Observable emitting with a delay" [data]="item" > </hello>
</ng-container>

Demo

【讨论】:

  • 这是个好主意,但这个答案的解决方案更短,做同样的stackoverflow.com/a/59249460/4166537
  • 是的,我本来打算添加这个作为另一个选项,但是因为我看到有人已经添加了它,所以我没有提及:)
【解决方案3】:

你可以简单地使用'startWith'运算符,就像你在你的observable中使用的那样,结果实际上是合乎逻辑的,因为observable不包含任何初始值,它打印null,尝试运算符startWith,或者它的变体@ Muhammed Albarmavi 在这里写下了(我建议使用 startwith),我知道您的实际代码中可能有很多复杂的数据结构,但是您也可以传递空数组空对象等

【讨论】:

  • 聚合 startWith 是正确的,其他答案只是一个工作 arround ?
【解决方案4】:

在请求完成之前提供默认值的简单方法

<hello 
name="Observable emitting with a delay" 
[data]="((delayedData$|async) || 'hello from earth ?')"> 
</hello>

demo ⚡

【讨论】:

  • 这也可能是解决方案,但它的行为与 startwith 运算符完全相同,但 start with 运算符是获得相同结果的更简洁的方法
  • @LashaSumbadze 是的,它只是一种替代方式,但我认为所有答案都可以很好地工作?
【解决方案5】:

这是 Angular 的一个已知错误,在本期中进行了解释(标记为提案,但它是一个错误) https://github.com/angular/angular/issues/16982

本讨论中列出了可能的解决方案。一般的解决方案是使用startWith rxjs 运算符,在模板中使用?.

还有一个 tslint 规则可以防止类似http://codelyzer.com/rules/template-no-negated-async/ 的情况发生

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-24
    • 2020-10-08
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 2019-06-26
    • 2016-01-30
    相关资源
    最近更新 更多