【Angular】Angular の オペレータまとめ

#オペレータとは
* オペレーターは、 **リアクティブプログラミング** で、Observableクラスで扱う **ストリームの高度な操作** を可能にするための関数です。
    * リアクティブプログラミング：流れてくるデータ（ストリーム）に関連性と操作を宣言的に記述する手法のことです
    * Observable：ストリームを扱うクラスです
        * 例：マウス操作やHTTPリクエストでデータ取得するなど
    * ストリームは川の様なイメージです
    * つまりオペレータは、川（ストリーム）の **中間で処理する仕組み** であり、流れてきたデータを下流でキャッチして、オブジェクト間のデータのやり取りをします

#主要なオペレータの使い方

##ofオペレータ
* 渡ってきたデータに何もせずそのまま流します

```ts
import { of } from 'rxjs';
const cats = of('cat1', 'cat2','cat3');
cats.subscribe(cat => console.log(cat)); // cat1, cat2, cat3
```    

##Mapオペレータ
* 渡ってきたデータを受け取って違うデータを返します

```ts
import { of } from 'rxjs';
import { map } from 'rxjs/operators';

const nums = of(1, 2, 3)
.pipe(
  map(num => num * num)
).subscribe(
  num  => console.log(num) // 1, 4, 9
);
```


##filterオペレータ
* 流れてきたデータチェックを行い、条件にあった場合のみ、ストリームが流れます
    * 文字列一致判定、typeOf演算子で、どの種類の演算子か判定するなどに使えます

```ts
import { of } from 'rxjs';
import { filter } from 'rxjs/operators';

const cats = of('mike', 'tama', 'mikeneko')
.pipe(
  filter(cat => cat === 'mike')
).subscribe(
  cat => console.log( `matched: ${cat}`) //matched: mike
);
```
    

##debounceTimeオペレータ
* 連続してデータを流すときに、指定時間遅延後、最後のデータを一度のみストリームを流します
    * `debounceTime(250)`では、250msec以下のストリームは流れない
* 何回も流れないように制御できます

```ts
import { of } from 'rxjs';
import { map, debounceTime } from 'rxjs/operators';

// 連続する最後の処理から250ミリ秒遅延後、最後のデータを1度だけストリームに流す
const nums = of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.pipe(
    debounceTime(250),
    map(value => `debounceTime(250): ${value}`)
)
.subscribe(
  value  => console.log(value) // debounceTime(250): 10
);
```

##throttleTimeオペレータ
* 連続してデータを流すときに、中間処理を250ミリ秒間隔で間引くことができます
    * windowのスクロールを間引きたいときなどに使います

```ts
import { of } from 'rxjs';
import { map, throttleTime } from 'rxjs/operators';

// 連続する処理を250ミリ秒間隔で間引く
const nums = of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.pipe(
    throttleTime(250),
    map(value => `throttleTime(250): ${value}`)
)
.subscribe(
  value  => console.log(value) // debounceTime(250): 1
);
```

##distinctUntilChangedオペレータ
* 前回とデータが違う時のみデータを流します
    * 同じデータを連続で流したくない時に使います

```ts
import { of } from 'rxjs';
import { distinctUntilChanged, map } from 'rxjs/operators';

// 前回と値が違う場合のみ、ストリームを流す
const cats = of('mike', 'mike', 'mike' ,'mikeneko')
.pipe(
    distinctUntilChanged(),
).subscribe(
    cat => console.log( `distinctUntilChanged: ${cat}` ) 
);

// distinctUntilChanged: mike
// distinctUntilChanged: mikeneko
```   

##switchMapオペレータ
* Stream Aに流れてくるデータを元に、別のStream Bを流します
* `Observable` を切り替えて、別の`Observable` を返すことができます
* 別のStream Bが終わる前に、元のStream A が流れた場合、途中までのStream Bはキャンセルされて、始めから再び実行されます
    * HTTPクライアントでリクエストを投げた後、処理を途中で止める時に使います

```ts
import { interval, of } from 'rxjs';
import { map, switchMap, take} from 'rxjs/operators';

const cats = of('mike', 'mike', 'mike' ,'mikeneko') // StreamA
.pipe(
    switchMap(cat => {
          return interval(1000).pipe( // StreamB
            take(3),
            map((index) => `switchMap: ${index} => ${cat}`)
          );
      })
  )       
.subscribe(
    cat => console.log( `${cat}` ) 
);
```

##skipオペレータ
* 指定した回数分、意図的にデータを流さない時に使います

```ts
import { of } from 'rxjs';
import { skip } from 'rxjs/operators';

const cats = of('mike', 'mike', 'mike' ,'mikeneko') 
.pipe(
    skip(2),
)       
.subscribe(
    cat => console.log( `skip: ${cat}` ) 
);

//skip: mike
//skip: mikeneko

```

##takeオペレータ
* 指定回数のみ実行するときに使います
    * 初めの一回のみ実行したいなど

```ts
import { of } from 'rxjs';
import { take } from 'rxjs/operators';

let count = 0;
const cats = of('mike', 'tama', 'mike' ,'mikeneko', 'tama') 
.pipe(
    take(3)
)       
.subscribe(
    cat => console.log( `take(${++count}): ${cat}` ) 
);

//take(1): mike
//take(2): tama
//take(3): mike
```

##finalizeオペレータ
* 引数で渡したコールバック関数を、ストリームが流れた最後に実行します
* ストリームが流れた最後に処理を行う時に使います
    * HTTPリクエストで画面にローディングアイコンを表示した際に、処理の再後にアイコンを非表示にするなど

```ts
import { interval } from 'rxjs';
import { map, take, finalize } from 'rxjs/operators';

interval(1000) // 1sずつカウントアップ
.pipe(
    map(index => `finalize(map): ${index + 1}`),
    take(3),
    finalize(() => {
      setTimeout(() => console.log( 'finalize!(ˆoˆ)' ) , 100);
    }),
)       
.subscribe(
    val => console.log( `${val}` ) 
);

// finalize(map): 1
// finalize(map): 2
// finalize(map): 3
// finalize!(ˆoˆ)
```

##(参考サイト)
* 様々なオペレータの動作を視覚的に確認できます🌟<br>
[RxJS marbles](https://rxmarbles.com/)