首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >vscode源码分析【五】事件分发机制

vscode源码分析【五】事件分发机制

作者头像
liulun
发布2019-07-02 17:34:10
1.7K0
发布2019-07-02 17:34:10
举报
文章被收录于专栏:liulunliulunliulun

在上一篇中,我们看到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);
				}
			}

循环派发了所有注册的事件

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-06-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档