`take(1)`と`first()`の違い
Angular, RxJS, Angular2-Observables: take(1)
vs first()
Angular、RxJS、Angular2-Observables のプログラミングにおける take(1)
と first()
の違いについて日本語で説明します。
take(1)
と first()
の共通点
- 両者とも、Observable が発する最初の値のみを抽出し、その後はサブスクライブを解除します。
- 完了条件
take(1)
: Observable が完了するか、最初の値が発せられたかのどちらか早い方でサブスクライブを解除します。first()
: Observable が完了するか、最初の値が発せられたかのどちらか早い方でサブスクライブを解除しますが、Observable が完了せずに最初の値が発せられなかった場合はエラーを投げます。
例
import { of, fromEvent } from 'rxjs';
import { first, take } from 'rxjs/operators';
// Observable が完了する前に最初の値が発せられる場合
const observable1 = of('a', 'b', 'c');
observable1.pipe(first()).subscribe(value => console.log(value)); // 出力: 'a'
// Observable が完了せずに最初の値が発せられない場合
const observable2 = fromEvent(document, 'click');
observable2.pipe(first()).subscribe(
value => console.log(value),
error => console.error(error)
); // クリックがされない限りエラーが発生します
// Observable が完了する前に最初の値が発せられる場合 (take(1))
const observable3 = of('a', 'b', 'c');
observable3.pipe(take(1)).subscribe(value => console.log(value)); // 出力: 'a'
// Observable が完了せずに最初の値が発せられない場合 (take(1))
const observable4 = fromEvent(document, 'click');
observable4.pipe(take(1)).subscribe(
value => console.log(value),
error => console.error(error)
); // クリックがされない限りエラーは発生しません
import { of } from 'rxjs';
import { take } from 'rxjs/operators';
const observable = of('a', 'b', 'c');
observable.pipe(take(1)).subscribe(value => {
console.log(value); // 出力: 'a'
});
take(1)
をパイプラインに適用すると、Observable が発する最初の値 ('a'
) を受け取った時点でサブスクライブが解除されます。残りの値 ('b'
,'c'
) は無視されます。
import { of, fromEvent } from 'rxjs';
import { first } from 'rxjs/operators';
const observable1 = of('a', 'b', 'c');
observable1.pipe(first()).subscribe(value => {
console.log(value); // 出力: 'a'
});
const observable2 = fromEvent(document, 'click');
observable2.pipe(first()).subscribe(
value => console.log(value),
error => console.error(error)
);
observable2
の場合は、クリックイベントが発生するまでサブスクライブが解除されません。クリックイベントが発生しなければ、エラーが投げられます。observable1
の場合は、最初の値 ('a'
) を受け取った時点でサブスクライブが解除されます。
import { of, fromEvent } from 'rxjs';
import { take, first } from 'rxjs/operators';
// Observable が完了する前に最初の値が発せられる場合
const observable1 = of('a', 'b', 'c');
observable1.pipe(first()).subscribe(value => console.log(value)); // 出力: 'a'
observable1.pipe(take(1)).subscribe(value => console.log(value)); // 出力: 'a'
// Observable が完了せずに最初の値が発せられない場合
const observable2 = fromEvent(document, 'click');
observable2.pipe(first()).subscribe(
value => console.log(value),
error => console.error(error)
); // クリックがされない限りエラーが発生します
observable2.pipe(take(1)).subscribe(
value => console.log(value),
error => console.error(error)
); // クリックがされない限りエラーは発生しません
- ただし、Observable が完了せずに最初の値が発せられない場合、
first()
はエラーを投げますが、take(1)
はエラーを投げません。 - 両者とも、Observable が完了する前に最初の値が発せられる場合は同じ結果になります。
take(1) の代替方法
a. filter()
と takeWhile()
の組み合わせ
import { of } from 'rxjs';
import { filter, takeWhile } from 'rxjs/operators';
const observable = of('a', 'b', 'c');
observable
.pipe(
filter(value => value === 'a'),
takeWhile(value => value === 'a')
)
.subscribe(value => console.log(value)); // 出力: 'a'
filter()
で最初の値 ('a'
) だけを抽出し、takeWhile()
でその条件が満たされる間だけサブスクライブを続けます。
b. reduce()
import { of } from 'rxjs';
import { reduce } from 'rxjs/operators';
const observable = of('a', 'b', 'c');
observable
.pipe(
reduce((acc, value) => {
if (acc === undefined) {
return value;
} else {
return acc;
}
})
)
.subscribe(value => console.log(value)); // 出力: 'a'
reduce()
を使用して、最初の値を保持し、以降の値を無視します。
first() の代替方法
a. find()
import { of } from 'rxjs';
import { find } from 'rxjs/operators';
const observable = of('a', 'b', 'c');
observable
.pipe(
find(value => value === 'a')
)
.subscribe(value => console.log(value)); // 出力: 'a'
find()
は、条件を満たす最初の値を返します。条件を満たす値が見つからない場合は、undefined
を返します。
b. single()
import { of } from 'rxjs';
import { single } from 'rxjs/operators';
const observable = of('a', 'b', 'c');
observable
.pipe(
single(value => value === 'a')
)
.subscribe(value => console.log(value)); // 出力: 'a'
single()
は、条件を満たす値がちょうど1つだけ存在する場合にその値を返します。条件を満たす値が複数存在するか、または存在しない場合はエラーを投げます。
- 適切な代替方法を選択することで、コードの可読性やパフォーマンスを向上させることができます。
take(1)
やfirst()
には、さまざまな代替方法が存在します。
angular rxjs angular2-observables