ホームページ > 記事 > ウェブフロントエンド > RxJS が Angular でデータ操作をどのようにマッピングするかについての簡単な説明
#マップ
データはプログラム開発中の一般的な操作です。 RxJS
を使用してコード内でデータ ストリームを生成する場合、最終的にはデータを必要な形式にマップする方法が必要になる可能性が高くなります。 RxJS
は、通常の map
関数に加えて、mergeMap
、switchMap
、および concatMap
関数を提供します。 。 [関連チュートリアルの推奨事項: "angular チュートリアル"]
map
演算子が最も一般的です。 Observable
によって出力される各値に対して、関数を適用してデータを変更できます。戻り値は、ストリーム内で引き続き使用できるように、バックグラウンドで Observable
として再リリースされます。配列で使用する場合と非常によく似た動作になります。
違いは、配列は常に単なる配列であるのに対し、マッピング時には配列内の現在のインデックス値を取得することです。 observable
の場合、データのタイプはさまざまなタイプになります。これは、望ましい結果を得るために、Observable map
関数でいくつかの追加操作を実行する必要がある可能性があることを意味します。次の例を見てください: :
import { of } from "rxjs"; import { map } from "rxjs/operators"; // 创建数据 const data = of([ { brand: "保时捷", model: "911" }, { brand: "保时捷", model: "macan" }, { brand: "法拉利", model: "458" }, { brand: "兰博基尼", model: "urus" } ]); // 按照brand model的格式输出,结果:["保时捷 911", "保时捷 macan", "法拉利 458", "兰博基尼 urus"] data.pipe(map(cars => cars.map(car => `${car.brand} ${car.model}`))).subscribe(cars => console.log(cars)); // 过滤数据,只保留brand为porsche的数据,结果:[{"brand":"保时捷","model":"911"},{"brand":"保时捷","model":"macan"}] data.pipe(map(cars => cars.filter(car => car.brand === "保时捷"))).subscribe(cars => console.log(cars));
まず、一連の車を含むオブザーバブルを作成します。次に、この Observable を 2 回サブスクライブします。
初めてデータを変更したとき、brand
と model
という文字列で接続された配列が得られました。
データを 2 回目に変更したとき、brand
が Porsche
だけを含む配列を取得しました。
両方の例で、Observable
マップ演算子を使用して、Observable
によって出力されるデータを変更します。変更された結果が返され、map
演算子は結果を監視可能なオブジェクトにカプセル化して、後で subscribe
できるようにします。
次に、配列を出力する監視可能なオブジェクトがあるシナリオがあると仮定します。配列内の各項目については、サーバーがデータを取得します。
これを行うには、配列をサブスクライブしてから、API 呼び出しを処理する関数を呼び出すマップを設定し、その結果をサブスクライブします。次のように:
import { of, from } from "rxjs"; import { map, delay } from "rxjs/operators"; const getData = param => { return of(`检索参数: ${param}`).pipe(delay(1000)); }; from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => console.log(val));
map
関数は getData
関数の値を返します。この場合、それは観察可能です。しかし、これは問題を引き起こします。今、私たちは対処しなければならない追加の観測対象物を抱えています。
これをさらに明確にするには: from([1,2,3,4])
「外部」オブザーバブルとして、getData()
の結果は " 「内部」の観察可能物。理論的には、外部観測可能量と内部観測可能量の両方を受け入れなければなりません。次のようになります。
import { of, from } from "rxjs"; import { map, delay } from "rxjs/operators"; const getData = param => { return of(`检索参数: ${param}`).pipe(delay(1000)); }; from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => val.subscribe(data => console.log(data)));
ご想像のとおり、これは Subscribe
を 2 回呼び出す必要があるという理想的な状況からは程遠いです。ここで mergeMap
が活躍します。 MergeMap
は本質的に mergeAll
と map
の組み合わせです。 MergeAll
は、「内部」の監視可能なオブジェクトをサブスクライブする役割を果たします。 MergeAll
が「内部」の監視可能なオブジェクトの値を「外部」の監視可能なオブジェクトにマージするとき、 2回購読する必要があります。次のように:
import { of, from } from "rxjs"; import { map, delay, mergeAll } from "rxjs/operators"; const getData = param => { return of(`检索参数: ${param}`).pipe(delay(1000)); }; from([1, 2, 3, 4]) .pipe( map(param => getData(param)), mergeAll() ) .subscribe(val => console.log(val));
これははるかに優れており、mergeMap
がこの問題に対する最良の解決策になります。完全な例は次のとおりです。
import { of, from } from "rxjs"; import { map, mergeMap, delay, mergeAll } from "rxjs/operators"; const getData = param => { return of(`检索参数: ${param}`).pipe(delay(1000)); }; // 使用 map from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => val.subscribe(data => console.log(data))); // 使用 map 和 mergeAll from([1, 2, 3, 4]) .pipe( map(param => getData(param)), mergeAll() ) .subscribe(val => console.log(val)); // 使用 mergeMap from([1, 2, 3, 4]) .pipe(mergeMap(param => getData(param))) .subscribe(val => console.log(val));
SwitchMap
も同様の動作をし、内部オブザーバブルにもサブスクライブします。ただし、switchMap
は switchAll
と map
を組み合わせたものです。 SwitchAll
以前のサブスクリプションをキャンセルし、新しいサブスクリプションに登録します。上記のシナリオでは、「外部」の監視可能な配列内の各項目に対して API 呼び出しを実行したいと考えていますが、switchMap
は最初の 3 つのサブスクリプションをキャンセルし、最後のサブスクリプションのみを処理するため、あまりうまく機能しません。サブスクリプション。つまり、得られる結果は 1 つだけです。完全な例はここで見ることができます:
import { of, from } from "rxjs"; import { map, delay, switchAll, switchMap } from "rxjs/operators"; const getData = param => { return of(`retrieved new data with param ${param}`).pipe(delay(1000)); }; // 使用 a regular map from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => val.subscribe(data => console.log(data))); // 使用 map and switchAll from([1, 2, 3, 4]) .pipe( map(param => getData(param)), switchAll() ) .subscribe(val => console.log(val)); // 使用 switchMap from([1, 2, 3, 4]) .pipe(switchMap(param => getData(param))) .subscribe(val => console.log(val));
switchMap
は現在のシナリオでは機能しませんが、他のシナリオでは機能します。これは、たとえば、フィルターのリストをデータ フローに結合し、フィルターが変更されたときに API 呼び出しを実行する場合に便利です。以前のフィルター変更がまだ処理中で、新しい変更が完了している場合は、以前のサブスクリプションがキャンセルされ、最新の変更に基づいて新しいサブスクリプションが開始されます。例は次のとおりです。
import { of, from, BehaviorSubject } from "rxjs"; import { map, delay, switchAll, switchMap } from "rxjs/operators"; const filters = ["brand=porsche", "model=911", "horsepower=389", "color=red"]; const activeFilters = new BehaviorSubject(""); const getData = params => { return of(`接收参数: ${params}`).pipe(delay(1000)); }; const applyFilters = () => { filters.forEach((filter, index) => { let newFilters = activeFilters.value; if (index === 0) { newFilters = `?${filter}`; } else { newFilters = `${newFilters}&${filter}`; } activeFilters.next(newFilters); }); }; // 使用 switchMap activeFilters.pipe(switchMap(param => getData(param))).subscribe(val => console.log(val)); applyFilters();
コンソールに示されているように、getData
はすべてのパラメータを 1 回だけログに記録します。 3 つの API 呼び出しを保存しました。
最後の例は concatMap
です。 concatMap
内部監視可能なオブジェクトをサブスクライブしました。ただし、switchMap
とは異なり、新しい観測オブジェクトが入ってくると、現在の観測オブジェクトのサブスクリプションがキャンセルされます。concatMap
は、現在の観測オブジェクトが完了するまで次の観測をサブスクライブしません。 。 物体。この利点は、観測可能なオブジェクトが信号を発する順序が維持されることです。これを実証するには:
import { of, from } from "rxjs"; import { map, delay, mergeMap, concatMap } from "rxjs/operators"; const getData = param => { const delayTime = Math.floor(Math.random() * 10000) + 1; return of(`接收参数: ${param} and delay: ${delayTime}`).pipe(delay(delayTime)); }; // 使用map from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => val.subscribe(data => console.log("map:", data))); // 使用mergeMap from([1, 2, 3, 4]) .pipe(mergeMap(param => getData(param))) .subscribe(val => console.log("mergeMap:", val)); // 使用concatMap from([1, 2, 3, 4]) .pipe(concatMap(param => getData(param))) .subscribe(val => console.log("concatMap:", val));
getData
函数的随机延迟在1到10000毫秒之间。通过浏览器日志,可以看到map
和mergeMap
操作符将记录返回的任何值,而不遵循原始顺序。concatMap
记录的值与它们开始时的值相同。
将数据映射到所需的格式是一项常见的任务。RxJS
附带了一些非常简洁的操作符,可以很好的完成这项工作。
概括一下:map
用于将normal
值映射为所需的任何格式。返回值将再次包装在一个可观察对象中,因此可以在数据流中继续使用它。当必须处理一个“内部”观察对象时,使用mergeMap
、switchMap
或concatMap
更容易。如果只是想将数据转成Observable
对象,使用mergeMap
;如果需要丢弃旧的Observable
对象,保留最新的Observable
对象,使用switchMap
;如果需要将数据转成Observable
对象,并且需要保持顺序,则使用concatMap
。
更多编程相关知识,请访问:编程视频!!
以上がRxJS が Angular でデータ操作をどのようにマッピングするかについての簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。