日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RxJs map operator 工作原理分析

發布時間:2023/12/19 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RxJs map operator 工作原理分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用一個例子來研究 map 操作符的工作原理。

推薦閱讀本文之前,先瀏覽這篇文章RxJs fromEvent 工作原理分析以了解相關知識。

源代碼:

import { Component, OnInit, Inject } from '@angular/core'; import { fromEvent, combineLatest } from 'rxjs'; import { mapTo, startWith, scan, tap, map } from 'rxjs/operators'; import { DOCUMENT } from '@angular/common';@Component({selector: 'app-combine-latest',templateUrl: './combine-latest.component.html' }) export class CombineLatestComponent implements OnInit {readonly document: Document;constructor(// https://github.com/angular/angular/issues/20351@Inject(DOCUMENT) document: any) {this.document = document as Document;}redTotal:HTMLElement;blackTotal: HTMLElement;total:HTMLElement; test:HTMLElement;ngOnInit(): void {this.redTotal = this.document.getElementById('red-total'); this.blackTotal = this.document.getElementById('black-total');this.total = this.document.getElementById('total');this.test = this.document.getElementById('test');combineLatest(this.addOneClick$('red'), this.addOneClick$('black')).subscribe(([red, black]: any) => {this.redTotal.innerHTML = red;this.blackTotal.innerHTML = black;this.total.innerHTML = red + black;});fromEvent(this.test, 'click').pipe(map( event => event.timeStamp)).subscribe((event) => console.log(event));}addOneClick$ = id =>fromEvent(this.document.getElementById(id), 'click').pipe(// map every click to 1mapTo(1),// keep a running totalscan((acc, curr) => acc + curr, 0),startWith(0)); }

打開頁面,點擊 Test 按鈕,能在 Chrome 控制臺里看到每次點擊發生時的 timestamp 時間戳:

下面介紹 map 操作符是如何起作用的。

先縷一縷順序:

  • 首先執行fromEvent,返回一個 Observable 對象。

  • 執行 map 操作符,其結果作為輸入,傳入 pipe

  • 2.執行 pipe:

  • 執行 subscribe 操作。
  • 我們可以把 pipe 形象地想象成管道,通過 fromEvent 返回的 Observable 對象,流過一根根管道,最后觸發其訂閱者,執行訂閱者的邏輯。那么 RxJs 提供的各種 operator,就是安裝在管道里的處理器。

    map 操作的輸入是我們定義的映射函數,在 RxJs 上下文里,稱為 project:

    map 返回一個新的函數,名為 mapOperation. 新函數體里,基于傳入的 project,創建一個新的 MapOperator. 這個 MapOperator,作為新函數輸入參數 source 的 lift 方法調用的輸入參數。到現在為止,我們尚且不知道 source 參數的類型。

    接下來執行 Observable 的 pipe 方法。

    operations 參數是 map operator 返回的新函數,mapOperation:

    pipeFromArray 的實現,如果 pipe 輸入只有一個 operator,這種情況比較簡單,進入第 9 行的 IF 分支,直接將 map 返回的 mapOperation 函數作為 pipeFromArray 調用的返回結果。

    注意到 Observable.js 實現里,在 pipeFromArray(operations) 返回之后,緊跟了另一個括號,說明這是另一個函數調用,輸入參數為 this,即 Observable 對象本身。

    現在進入到 map 操作返回的 新函數 mapOperation 的函數體內部了:

    因為此時 button 尚未點擊,因此 Observable 對象并沒有 emit 值,只是完成相關的 setup 工作。

    這行語句:

    return source.lift(new MapOperator(project, thisArg));

    只是返回一個新的 Observable 對象,其 source 屬性指向調用 lift 操作的原始 Observable 對象,而 operator 屬性指向 new MapOperator 返回的結果,后者是 project 的 wrapper.

    如此一來,調用 subscribe 方法注冊應用程序監聽函數的 Observable 對象,再也不是 fromEvent 返回的原始 Observable 對象,而是前者調用了 pipe,接收了 map 指定的 project 之后,由 source.lift( new MapOperator) 返回的新 Observable 對象。

    這個新的 Observable 對象,調用 subscribe 方法,執行邏輯和這篇文章RxJs fromEvent 工作原理分析介紹的相比有所差異,復雜度稍稍增加了。

    把 Observable 對象 operator 屬性值提取出來:

    接下來的 21行代碼執行,和之前沒有 operator 時相比,沒有差異,略過。

    前一篇文章進入 ELSE 分支,而本文因為 operator 的存在,進入 22 行的 IF 分支:

    首先執行 operator.call 方法:

    MapSubscriber 也是 Subscriber 的子類之一,和其父類相比,多了 project 屬性。

    再次執行 subscribe:

    因為這次傳入的 Observable 是最原始的即 fromEvent 返回的 Observable,因此不存在 operator,所以進入 ELSE 分支執行:

    重點分析 this 和 sink:

    this 是 fromEvent 返回的原始 Observable,而 sink 是包含了 map operator 以及應用程序定義的訂閱邏輯的 Subscriber:

    _trySubscribe 調用 _subscribe:

    最終仍舊進入了 fromEvent 的核心邏輯:

    這段代碼,定義了 fromEvent,以什么樣的方式,emit 何種類型的數據。

    • 什么樣的方式?addEventListener,每次 eventTarget 定義的 HTMLElement 發生 click 事件時,emit 數據
    • emit 的數據格式為 MouseEvent.

    至此 Observable 相關的 setup 執行完畢。

    點擊按鈕,觸發之前通過 addListener 注冊的 handler 函數。fromEvent.js 此處 subscriber 不是原始的 subscriber,而是 MapSubscriber,其 destination 屬性的 _next, 指向了應用程序指定的訂閱處理邏輯。Emit 的數據是 MouseEvent.

    MapSubscriber 的特色:在將原始值 MouseEvent 交給應用程序之前,先要執行 project 對其進行處理:

    這個 project 的邏輯是,將 MouseEvent 對象映射成 timestamp 時間戳:

    將 project 處理結果返回給destination 繼續進行傳遞:

    this._next 指向的是應用程序定義的 console.log(event), 在這里得到執行:

    更多Jerry的原創文章,盡在:“汪子熙”:

    總結

    以上是生活随笔為你收集整理的RxJs map operator 工作原理分析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。