Web Workers 是在HTML5中新增的,用来在web应用程序中实现后台处理的一种技术。在HTML4中,js创建的程序都是单线程的,如果花费时间比较长的话web界面就会长时间没有响应,最恶劣的情况还会跳出一个脚本提示框:“提示脚本运行时间过长,是否继续?”于是就引出了Web Workers API。
在MapboxGL中为了避免加载地图数据时耗时太长导致阻塞,采用了Web Workers技术,在后台创建了三个线程,耗时较长的工作都在后台线程中完成。其核心是“webworkify”模块,它是运行在node中的web workers模型,也是通过postMessage和onMessage实现线程间的通信。
在MapboxGL中用于完成对象间的通信的主要有三个对象:
Actor对象
Actor对象主要作用就是完成线程间的消息传递,主要包括三个函数:
1. receive()
2. send()
3. postMessage()
receive()函数主要处理从线程内发到主线程的消息,send()函数通过调用postMessage()发送消息。
Dispacher对象
Dispacher对象在主线程中,通过该对象向后台线程发送消息,并在后天线程中进行处理。
Worker对象
Worker对象封装了后台线程的执行文件,其内部的代码对浏览器而言是不可见的,相当于后台。MapboxGL相关地图数据的加载,图标、注记等缓冲区的建立都是在后台线程进行处理。通过Dispacher对象向Worker对象发送消息,worker对象根据消息类型进行相应的处理。在worker对象内部,通过Actor对象发送消息与主线程进行通信。
例如,在worker对象内部通过发送一个“debug”类型的消息:
this.actor.send('debug',tile.data);
在Actor对象的receive()函数中添加该类型消息的处理函数:
if (data.type === '<response>'){ //如果是响应消息,表明子线程已处理完成,执行回调函数
callback = this.callbacks[data.id];
delete this.callbacks[data.id];
callback(data.error || null, data.data);
} else if (data.type === 'debug'){//从子线程传回的调试消息
console.log("以下为调试消息:");
console.log(data.data);
console.log("调试结束");
}
这样就可以调试从后台线程传回的变量,执行后在控制台就可以看到以下消息: