簡體   English   中英

我的反應事件池偽示例有意義嗎?

[英]My react event pooling pseudo example makes sense?

TLDR

我可以檢查有關反應中event pooling邏輯的實現嗎?
我想知道event pooling原理:)

問題

當我深入研究響應文檔時,我看到了event pooling
所以,我很好奇什么是event pooling ,我研究了它。

現在我意識到thread pooling 所以它的工作方式類似。 所以我做了一些偽event pooling邏輯。
我想知道這有意義嗎?

任何知道event pooling實現在哪里的人都會react package。
請給我評論

偽事件池

EventPool 偽實現

class EventPool {
  private static instance: EventPool;
  private taskQueue: Event[] = [];
  private constructor() {
    this.taskQueue = [];
  }

  public static shared() {
    if (!EventPool.instance) {
      EventPool.instance = new EventPool();
    }
    return EventPool.instance;
  }

  enqueue = (event: Event) => {
    this.taskQueue = this.taskQueue.concat(event);
  };

  dequeue = (currentTarget: any) => {
    this.taskQueue = this.taskQueue.filter(
      (event: Event) => event.currentTarget === currentTarget
    );
  };

  clear() {
    // This function called before or after render 
    // (Commit -> Render -> EventPool.shared().clear()) or (Commit -> EventPool.shared().clear() -> Render) 
    this.taskQueue = this.taskQueue.filter((event) => event.isDone === true);
  }
}

關於persist的事件偽實現

class Event {
  persist = () => {
    // This is executed before EventPool.shared.clear
    EventPool.shared().dequeue(this);
  };
}

參考

  1. 什么是反應中的事件池? - 堆棧溢出
  2. 合成事件 - React 文檔
  3. 事件池的含義是什么?
  4. 진보된 쓰레드 풀링 기법 구현 - 韓語

這是SyntheticEvent / EventPool模式的非常簡單的示例。 顯然,在現實生活中,更好地尊重事件的行為會有點復雜,但這個片段必須闡明一些概念。

class SyntheticEvent {
    // all the following properties and methods are part of React's
    // synthetic event, but we'll skip it here in favor of simplicity

    // bubbles: boolean
    // currentTarget: DOMEventTarget
    // defaultPrevented: boolean
    // eventPhase: number
    // nativeEvent: DOMEvent
    // preventDefault(): void {}
    // isDefaultPrevented(): boolean { return true }
    // stopPropagation(): void {}
    // isPropagationStopped(): boolean { return true }
    // target: DOMEventTarget
    // timeStamp: number
    // type: string

    // for simplicity we'll consider here only 3 following properties
    isTrusted: boolean
    cancelable: boolean
    persist: () => void

    // this property helps to track status of each synthetic event
    status: 'POOLED' | 'PERSISTED' | 'IN_USE'

    constructor(status, onPersist: () => void) {
        this.status = status;
        this.persist = onPersist;
    }
}

class EventPool {
    private pool: SyntheticEvent[] = [];

    constructor(initialPoolSize: number) {
        // populating pool with pre-allocated events. We will try to re-use
        // them as much as possible to reduce GC load
        for(let i = 0; i < initialPoolSize; i++) {
            this.allocateNewEvent();
        }
    }

    pullEvent(nativeEvent): SyntheticEvent {
        const syntheticEvent = this.getEventFromPool();
        this.populateEvent(syntheticEvent, nativeEvent);
        return syntheticEvent;
    }

    tryPushEvent(syntheticEvent: SyntheticEvent): void {
        if(syntheticEvent.status !== 'PERSISTED') {
            this.clearEvent(syntheticEvent);
        }
    }


    private allocateNewEvent(): SyntheticEvent {
        const newEvent = new SyntheticEvent( 'POOLED', () => {
            newEvent.status = 'PERSISTED';
        });
        this.pool.push(newEvent);
        return newEvent;
    }

    private getEventFromPool() {
        let event = this.pool.find( e => e.status === 'POOLED' );
        if(!event) {
            event = this.allocateNewEvent();
        }

        return event;
    }

    /** Populates synthetic event with data from native event */
    private populateEvent(syntheticEvent: SyntheticEvent, nativeEvent) {
        syntheticEvent.status = 'IN_USE';
        syntheticEvent.isTrusted = nativeEvent.isTrusted;
        syntheticEvent.cancelable = nativeEvent.cancelable;
    }

    /** Sets all previously populated synthetic event fields to null for safe re-use */
    private clearEvent(syntheticEvent: SyntheticEvent) {
        syntheticEvent.status = 'POOLED';
        syntheticEvent.isTrusted = null;
        syntheticEvent.cancelable = null;
    }
}

// Usage
const mainEventPool = new EventPool(2);
smth.onClick = nativeEvent => {
    const syntheticEvent = mainEventPool.pullEvent(nativeEvent);
    userDefinedOnClickHandler(syntheticEvent); // <-- on click handler defined by user
    mainEventPool.tryPushEvent(syntheticEvent);
};

事件池——React 使用 SyntheticEvent,它是原生瀏覽器事件的包裝器,因此它們在不同瀏覽器中具有一致的屬性。 我們在任何 react-app 中擁有的事件處理程序實際上是傳遞 SyntheticEvent 的實例,除非我們使用 nativeEvent 屬性來獲取底層瀏覽器事件。

包裝本機事件實例可能會導致性能問題,因為創建的每個合成事件包裝器也需要在某些時候進行垃圾收集,這在 CPU 時間方面可能會很昂貴。

React 通過分配一個合成實例池來處理這個問題。 每當觸發事件時,它都會從池中獲取一個實例並填充其屬性並重用它。 當事件處理程序完成運行時,所有屬性都將被取消,合成事件實例被釋放回池中。 因此,提高性能。

https://stackoverflow.com/a/53500357/1040070

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM