其实这样的选择是对的,从如今的情况来看,所谓的共享资源和互斥锁的多线程模型,带来的好处有限,麻烦却一大堆,实在不能说是一个很好的设计。是值得检讨而不是发扬光大的模型。
首先,webworker 不是伪多线程,一般我们说 js 中的伪多线程是指使用像 setTimeout setInterval 这样的 api 来实现类似并行的效果,而 webworker 是真正起了一个新线程的,所以它是真多线程。
这里的多线程并不是像web worker一样的伪多线程,而是类似java一样的真多线程,该线程,和其他线程共享全局变量,需要对共享变量用锁保护。
根据题主这句话,我猜测题主说 webworker 是伪多线程是因为 webworker 不能和主线程或其他子线程共享全局变量,也自然谈不上什么对共享变量的锁保护。可事实上,是不是多线程,和线程之间能不能共享全局变量并没有什么直接关系。可以参看维基百科上面关于线程的描述:
https:// zh.wikipedia.org/wiki/% E7%BA%BF%E7%A8%8B1. 会对开发者有什么影响(好处or坏处更多一点)?
2. 对js语言本身有什么影响?(会限制某些功能,某些场景?)
3. 和异步的api怎么兼容?
关于题主的这三个问题,我觉得其实不太好回答。因为一旦引入题主所说的可共享变量的多线程机制,整个 javascript 开发模型可能都得一起改变,这么大的变化,已经没法估量它带来的好处多还是坏处多了。
我们都知道 javascript 运行时,不管是 Chrome 的 V8 还是 Edge 的查克拉,都是基于 EventLoop 的。这意味着,每时每刻都只有一段用户代码可能修改环境中的变量,这个看似限制颇多的运行时模型使得 javascript 的开发模型大为简化。一旦引入可共享变量的多线程机制,就算传统的 EventLoop 机制仍然保留,也仍然可能会出现有两段代码同时修改某个变量,这无疑使得代码的编写和调试难度大大增加。
还有一些问题,比如,引入题主所谓的真多线程之后,原来的用户事件、setTimeout、setInterval 这些api的回调,是仍然放入 EventLoop 还是在新线程并行执行?浏览器的渲染线程会被 javascript 的执行线程阻塞,引入可共享变量的子线程后,子线程的执行要不要也阻塞浏览器渲染?
总的来说,目前浏览器上 javascript 已有的这些运行时模型基本满足了绝大部分的业务需求,同时又使编程模型复杂度保持在了很低的水平,已经是很好的权衡,并不太需要引入可共享变量的多线程这个新技术。
------------ 2016-09-23 13:57:18 更新-------------------
针对题主补充的内容,做一点补充
但另一个方面settimeout,以及异步(promise async/await),都是通过类似event loop的原理实现的,都运行在同一个线程里,当这个线程任务比较繁重,可能导致timeout不够准确,异步任务等待得比较久等缺点,能否通过vm层的多线程支持而有更好的体验呢(这样timeout和async/await运行在另一个线程,timeout更准确,异步任务也更及时)?比如类似C#一样,异步就新开一个线程,在里面干活,干完数据送回主线程,主线程可能阻塞,也可能做自己的事情,这样是不是一种比js真多线程更好的解决方案?
题主说到了setTimeout不准时的问题,我猜题主对这个不准时的原因理解可能有偏差。从我之前看过的一些资料来看,setTimeout不准时并不是因为定时器没有在指定的时间被触发,而是触发之后回调函数没有被立刻执行,这是两个完全不同的概念。比如 setTimeout(fn, 500) 这句代码会让 javascript 引擎在 500ms 后准时地将 fn 加入 EventLoop ,但是 EventLoop 是不是会立刻执行 fn 的内容就不好说了,这要看 fn 前面是不是还有别的什么任务。
而C#里面一般定时器的回调都是在单独线程里面执行的,其执行上下文和主线程是相对独立的,自然也就不存在要看前面是不是有其他任务要运行的问题,所以看上去执行时机更准确。
但是 C# 的多线程也没这么简单。如何更新 UI ?题主如果用 C# 写过客户端程序应该记得,子线程是没有办法直接操作界面的,需要用委托 delegate,其实也可以说就是一种消息,在子线程触发计时器之后,给 UI 线程发消息(调用delegate),让 UI 线程更新用户界面。
C# 这种做法,你用现有的 webworker 一样可以实现,在 worker 里面开计时器,到时间之后给主线程 postMessage ,主线程收到指定消息之后操作UI。可是,你怎么保证主线程收到消息的时候不忙碌可以立即处理消息更新 UI ?是不是感觉弄了半天还是绕回来了?呵呵