vscode源碼分析【五】事件分發機制

第一篇: vscode源碼分析【一】從源碼運行vscode
第二篇:vscode源碼分析【二】程序的啓動邏輯,第一個窗口是如何建立的
第三篇:vscode源碼分析【三】程序的啓動邏輯,性能問題的追蹤
第四篇:vscode源碼分析【四】程序啓動的邏輯,最初建立的服務

在上一篇中,咱們看到lifecycleService監聽了不少electron原生的事件,
監聽了以後,一旦事件被觸發,vscode是怎麼派發這些事件的呢?

在入口程序的startup方法中(src\vs\code\electron-main\main.ts),有這麼一句:html

once(lifecycleService.onWillShutdown)(() => (configurationService as ConfigurationService).dispose());

上面這句話語義好直白呀!一旦lifecycle裏發生了willShutdown的事件,就執行後面的回調函數!
那咱們看看lifecycle裏的這個onWillShutdown(src\vs\platform\lifecycle\electron-main\lifecycleMain.ts)promise

private readonly _onWillShutdown = this._register(new Emitter<ShutdownEvent>());
readonly onWillShutdown: Event<ShutdownEvent> = this._onWillShutdown.event;

發現它是被_register註冊的,這個文件裏並無_register函數,函數在它的父類Disposable裏(src\vs\base\common\lifecycle.ts)
我一直覺得這是資源釋放的類,沒想到還有事件相關的內容,哈!app

private readonly _store = new DisposableStore();
protected _register<T extends IDisposable>(t: T): T {
		if ((t as any as Disposable) === this) {
			throw new Error('Cannot register a disposable on itself!');
		}
		return this._store.add(t);
	}

 看來,還得看DisposableStore的add方法:electron

public add<T extends IDisposable>(t: T): T {
		if (!t) {
			return t;
		}
		if ((t as any as DisposableStore) === this) {
			throw new Error('Cannot register a disposable on itself!');
		}

		markTracked(t);
		if (this._isDisposed) {
			console.warn(new Error('Registering disposable on object that has already been disposed of').stack);
			t.dispose();
		} else {
			this._toDispose.add(t);
		}

		return t;
	}

markTracked這個方法不用管,裏面什麼也沒幹!
_toDispose就是個set,用來存你傳入的事件的;
另外,這個函數有個特別之處,就是你餵了它什麼它就拉了什麼出來!
由於咱們餵了它一個Emitter的實例,那咱們就去看看Emitter(src\vs\base\common\event.ts)
這是個泛型類型
有個get屬性:函數

get event(): Event<T> { //......

上面說的:源碼分析

this._onWillShutdown.event;

取.event的時候,執行的就是這裏,它其實返回了一個方法:post

this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => { //......

好!打住!看到這裏咱們先不去看這個方法的具體邏輯,
先返回頭來看最開始時main.ts裏的那個once方法:(src\vs\base\common\functional.ts)性能

export function once<T extends Function>(this: any, fn: T): T {
	const _this = this;
	let didCall = false;
	let result: any;

	return function () {
		if (didCall) {
			return result;
		}

		didCall = true;
		result = fn.apply(_this, arguments);

		return result;
	} as any as T;
}

很好理解,傳入一個方法,返回一個方法,
咱們知道,咱們傳入的是:this

lifecycleService.onWillShutdown

前面咱們說了,它確實是一個方法;
這個once還返回了一個匿名函數;
咱們經過這個匿名函數,把咱們的事件處理邏輯,綁定給了:lifecycleService.onWillShutdown
這是綁定的關鍵代碼:url

result = fn.apply(_this, arguments);

OK!咱們再去看那個this._event返回的方法具體幹了啥?!
傳入的參數,listener是咱們的匿名回調函數

() => (configurationService as ConfigurationService).dispose()

Emitter實例的_listeners屬性已經在別處初始化成了LinkedList的實例;

const remove = this._listeners.push(!thisArgs ? listener : [listener, thisArgs]);

這句話把咱們的匿名回調函數加到這個LinkedList中去了
好,以上是綁定事件,
咱們再來看看這個事件被觸發的時候是怎樣的

this._onWillShutdown.fire({
			join(promise) {
				if (promise) {
					joiners.push(promise);
				}
			}
		});

在這個fire方法中:

for (let iter = this._listeners.iterator(), e = iter.next(); !e.done; e = iter.next()) {
				this._deliveryQueue.push([e.value, event]);
			}

			while (this._deliveryQueue.size > 0) {
				const [listener, event] = this._deliveryQueue.shift()!;
				try {
					if (typeof listener === 'function') {
						listener.call(undefined, event);
					} else {
						listener[0].call(listener[1], event);
					}
				} catch (e) {
					onUnexpectedError(e);
				}
			}

循環派發了全部註冊的事件  

相關文章
相關標籤/搜索