第一篇: 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); } }
循环派发了全部注册的事件