第一篇: 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); } }
循環派發了全部註冊的事件