将在 RxJS 中通过管道传输 运行 的间隔吗?
Will an interval which got piped run in RxJS?
在 RxJS 中 运行 的间隔会被管道化吗?
这就是我的意思。假设我们有以下代码:
const arr = ["foo", "bar"];
const i = interval(500);
const toRun = i.pipe(
map(index => arr[index]),
take(arr.length)
);
toRun.subscribe(val => val);
我理解正确吗,代码的工作原理如下:
1 i
已创建,但在我们订阅它之前不会是 运行。
2 在 pipe
方法的帮助下,我们创建了一个新的 Observable
,它建立在 i
的基础上,工作方式如下:
- 每 500 毫秒发出一个迭代数 (0, 1, 2, ...)
- 使用迭代次数从
arr
中提取一个值
- 将提取的值发送给订阅
pipe
方法结果的任何人
- 当迭代次数大于
arr.length
时停止发射迭代次数
因此,toRun.subscribe(val => val);
将发出 foo
,然后在 500 毫秒后 bar
将停止 运行ning。虽然 i
永远不会发出任何东西,因为没有人订阅它。
我想了解这是如何工作的,所以,如果我错了,请更正我的解释以回答我的问题。
我在阅读 Angular 文档时偶然发现了其他问题。更具体地说是通过 async pipe。我在那里遇到了以下示例:
import { Component } from '@angular/core';
import { Observable, interval } from 'rxjs';
import { map, take } from 'rxjs/operators';
@Component({
selector: 'app-hero-message',
template: `
<h2>Async Hero Message and AsyncPipe</h2>
<p>Message: {{ message$ | async }}</p>
<button (click)="resend()">Resend</button>`,
})
export class HeroAsyncMessageComponent {
message$: Observable<string>;
private messages = [
'You are my hero!',
'You are the best hero!',
'Will you be my hero?'
];
constructor() { this.resend(); }
resend() {
this.message$ = interval(500).pipe(
map(i => this.messages[i]),
take(this.messages.length)
);
}
}
而且我很好奇是否由于 interval(500)
的不必要 运行 可能会出现性能问题(因为 pipe
将创建一个新的可观察对象并且 interval(500)
不会被显式使用,而只能在新的可观察对象创建期间被 pipe
使用。
你理解的差不多了。一些注意事项:
- 是的,
interval
创建了一个 cold observable,它只会在订阅时生成数字。
pipe
本身不会创建新的可观察对象,pipe
中的运算符会。
map
和 take
不会使 observable 变热,所以它仍然很冷,只有在订阅时才会 "run"。
interval
最初等待 500 毫秒,然后发出 foo
(订阅后)
take
将在给定的排放量后取消订阅其可观察到的来源。这将导致链中的每个 Observable 取消订阅其源,直到最终 interval
将被取消订阅。所以它不再发出数字。
您的想法是正确的,您的代码应该按预期工作,但它看起来不像应该使用 RxJs 的方式。从运算符内部访问闭包变量似乎是反对 RxJs 鼓励的无副作用纯度的危险信号。
在 RxJs 中有很多方法可以做某事;如果您开始以 RxJS 的方式思考,那么您将找到一种正确的解决方案。对于您的情况,这两个提示将带您走向正确的方向:
- 只要有数组可以从中获取值,请考虑如何使用
from, of
等 RxJs 工具从中提取可观察值
- 想一想如何组合多个可观察值并让它们协调以产生正确的结果。
用此代码替换您的 toRun
作业:
import {from, interval, zip} from "rxjs";
// ...
const toRun = zip(from(arr),i); // where i is interval(500)
此解决方案是一个简单但完美的示例,说明了如何使用这两个技巧。它更简洁,而且性能可能更好。
在幕后,from
将数组变成一个可观察对象,而 zip
使用间隔可观察对象的频率到 "moderate" 数组可观察对象的输出。 Observables 像这样交互是一种典型的模式,您会在 RxJs 的工作方式中经常看到。
注意:作为在 subscribe
处理程序中使用 zip
的奖励。你不仅会得到间隔值,还会得到相应的数组值,这些值是在数组参数中传递的。
在 RxJS 中 运行 的间隔会被管道化吗?
这就是我的意思。假设我们有以下代码:
const arr = ["foo", "bar"];
const i = interval(500);
const toRun = i.pipe(
map(index => arr[index]),
take(arr.length)
);
toRun.subscribe(val => val);
我理解正确吗,代码的工作原理如下:
1 i
已创建,但在我们订阅它之前不会是 运行。
2 在 pipe
方法的帮助下,我们创建了一个新的 Observable
,它建立在 i
的基础上,工作方式如下:
- 每 500 毫秒发出一个迭代数 (0, 1, 2, ...)
- 使用迭代次数从
arr
中提取一个值
- 将提取的值发送给订阅
pipe
方法结果的任何人 - 当迭代次数大于
arr.length
时停止发射迭代次数
因此,toRun.subscribe(val => val);
将发出 foo
,然后在 500 毫秒后 bar
将停止 运行ning。虽然 i
永远不会发出任何东西,因为没有人订阅它。
我想了解这是如何工作的,所以,如果我错了,请更正我的解释以回答我的问题。
我在阅读 Angular 文档时偶然发现了其他问题。更具体地说是通过 async pipe。我在那里遇到了以下示例:
import { Component } from '@angular/core';
import { Observable, interval } from 'rxjs';
import { map, take } from 'rxjs/operators';
@Component({
selector: 'app-hero-message',
template: `
<h2>Async Hero Message and AsyncPipe</h2>
<p>Message: {{ message$ | async }}</p>
<button (click)="resend()">Resend</button>`,
})
export class HeroAsyncMessageComponent {
message$: Observable<string>;
private messages = [
'You are my hero!',
'You are the best hero!',
'Will you be my hero?'
];
constructor() { this.resend(); }
resend() {
this.message$ = interval(500).pipe(
map(i => this.messages[i]),
take(this.messages.length)
);
}
}
而且我很好奇是否由于 interval(500)
的不必要 运行 可能会出现性能问题(因为 pipe
将创建一个新的可观察对象并且 interval(500)
不会被显式使用,而只能在新的可观察对象创建期间被 pipe
使用。
你理解的差不多了。一些注意事项:
- 是的,
interval
创建了一个 cold observable,它只会在订阅时生成数字。 pipe
本身不会创建新的可观察对象,pipe
中的运算符会。map
和take
不会使 observable 变热,所以它仍然很冷,只有在订阅时才会 "run"。interval
最初等待 500 毫秒,然后发出foo
(订阅后)take
将在给定的排放量后取消订阅其可观察到的来源。这将导致链中的每个 Observable 取消订阅其源,直到最终interval
将被取消订阅。所以它不再发出数字。
您的想法是正确的,您的代码应该按预期工作,但它看起来不像应该使用 RxJs 的方式。从运算符内部访问闭包变量似乎是反对 RxJs 鼓励的无副作用纯度的危险信号。
在 RxJs 中有很多方法可以做某事;如果您开始以 RxJS 的方式思考,那么您将找到一种正确的解决方案。对于您的情况,这两个提示将带您走向正确的方向:
- 只要有数组可以从中获取值,请考虑如何使用
from, of
等 RxJs 工具从中提取可观察值
- 想一想如何组合多个可观察值并让它们协调以产生正确的结果。
用此代码替换您的 toRun
作业:
import {from, interval, zip} from "rxjs";
// ...
const toRun = zip(from(arr),i); // where i is interval(500)
此解决方案是一个简单但完美的示例,说明了如何使用这两个技巧。它更简洁,而且性能可能更好。
在幕后,from
将数组变成一个可观察对象,而 zip
使用间隔可观察对象的频率到 "moderate" 数组可观察对象的输出。 Observables 像这样交互是一种典型的模式,您会在 RxJs 的工作方式中经常看到。
注意:作为在 subscribe
处理程序中使用 zip
的奖励。你不仅会得到间隔值,还会得到相应的数组值,这些值是在数组参数中传递的。