第一篇: vscode原始碼分析【一】從原始碼執行vscode
第二篇:vscode原始碼分析【二】程式的啟動邏輯,第一個視窗是如何建立的
第三篇:vscode原始碼分析【三】程式的啟動邏輯,效能問題的追蹤
第四篇:vscode原始碼分析【四】程式啟動的邏輯,最初建立的服務
在上一篇中,我們看到lifecycleService監聽了很多electron原生的事件,
監聽了之後,一旦事件被觸發,vscode是怎麼派發這些事件的呢?
在入口程式的startup方法中(src\vs\code\electron-main\main.ts),有這麼一句:
once(lifecycleService.onWillShutdown)(() => (configurationService as ConfigurationService).dispose());
上面這句話語義好直白呀!一旦lifecycle裡發生了willShutdown的事件,就執行後面的回撥函式!
那我們看看lifecycle裡的這個onWillShutdown(src\vs\platform\lifecycle\electron-main\lifecycleMain.ts)
private readonly _onWillShutdown = this._register(new Emitter<ShutdownEvent>());
readonly onWillShutdown: Event<ShutdownEvent> = this._onWillShutdown.event;
發現它是被_register註冊的,這個檔案裡並沒有_register函式,函式在它的父類Disposable裡(src\vs\base\common\lifecycle.ts)
我一直以為這是資源釋放的類,沒想到還有事件相關的內容,哈!
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方法:
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的時候,執行的就是這裡,它其實返回了一個方法:
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;
}
很好理解,傳入一個方法,返回一個方法,
我們知道,我們傳入的是:
lifecycleService.onWillShutdown
前面我們說了,它確實是一個方法;
這個once還返回了一個匿名函式;
我們通過這個匿名函式,把我們的事件處理邏輯,繫結給了:lifecycleService.onWillShutdown
這是繫結的關鍵程式碼:
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);
}
}
迴圈派發了所有註冊的事件