前言
众所周知,js是单线程的去跑代码,如果使用一个较长时间的循环来执行代码,浏览器就会卡死,直到js执行完毕,用户体验极差;因此对于较长时间的代码块,最好使用多线程去执行,关于这一点网上说可以用Dedicated Worker和Shared Worker来实现,在此不再赘述;
然而,在微信小程序中,也想用js实现多线程怎么办呢?API中为我们提供了一个方法,多线程 Worker,然而,如图所示:
worker只能创建一个,这也不行,那也不行;
关键是worker中不能使用wx对象,主js与worker通信只能通过参数传递的方式,然而参数只能是字符串json串之类的东西,不能传递对象与方法(本人亲测),本来想使用wx创建一个对象然后传递给worker的,然而并不行,这就很难受。
总而言之,截止到2020.6.2,微信小程序的多线程方法限制太多,很难用。(js的多线程有些复杂,还没试好不好用)
黑科技实现多线程
以下是本人实现多线程的方法,如果有大佬已经知道了,可以直接跳过。
1.核心方法:
//通常写法
setTimeout(function(){alert("abc")}, 1000);
//另一种写法
//setTimeout(function, milliseconds, param1, param2, ...)
function a(txt){
alert(txt);
}
setTimeout(a, 5000, "123");
2.setTimeout简介
setTimeout可以设置一个延时执行的方法,可以传入参数,可以传入对象,可以通过对象执行方法;当延迟时间设置为0时,基本就相当于多线程了,完全不会影响主线程的执行。
本人在微信小程序中遇到了不得不使用"多"线程的地方(那个worker是真的不能用,完全实现不了目的),找了半天,突然想到可以用setTimeout来实现多线程,迫不及待地尝试了一下,虽然还比不上其它语言的专业的多线程,但是完全可以实现了本人的需求。
3.setTimeout多线程
需要给线程传参数?直接传给setTimeout中的方法就行了;
线程需要操作其它变量和方法?将其它变量和方法声明成全局的就行了;
需要获取线程返回值?用几个全局变量,标一下线程id和参数内容就行了,当线程修改了id变量和内容变量时,主线程获取就行了;
需要判断线程是否执行完毕?再用几个全局变量,当线程执行完毕后修改全局变量,然后主线程就能知道线程是否执行完毕了;
需要终止线程?setTimeout也可以实现,使用var t = setTimeout(...); 然后使用clearTimeout(t); 即可。
还有其它需求?嗯......本人暂时没有了,但是感觉setTimeout基本都可以巧妙地实现。
4.setTimeout实现sleep方法
在js与微信小程序中,是没有原生的sleep方法的;上文提到,js是单线程的去跑代码,如果使用一个较长时间的循环来执行代码,浏览器就会卡死,直到js执行完毕;有人利用这一点实现js的sleep方法,确实可以使得延迟一段时间后继续执行下方的代码,但是这期间浏览器是卡死状态的,无法响应其它事件,用户体验很不好。
因此,使用setTimeout实现的sleep方法是比较方便的,只需要修改下代码逻辑,让后续代码延迟指定时间后执行即可,在此期间页面可以响应其它事件,比如用户可以点击按钮来取消后续代码的执行(而如果使用循环来延时执行后续代码,浏览器是不会响应其余事件的,很不灵活,而且页面处于卡死状态,用户体验极差)。
目前本人认为setTimeout是JS和微信小程序中最好用的多线程方法了(至少实现了本人微信小程序中的需求)
总结
使用setTimeout可以在js与微信小程序中实现多线程,虽然可能不如其它语言中的多线程方法,不过本人感觉一般的多线程需求基本上都可以实现了;至于多线程共享数据需要加锁之类的,本人还没有研究过,不过感觉似乎也可以巧妙地实现。如果大家发现哪些地方setTimeout实现的多线程还不完美,欢迎下方留言讨论;如果有更好的js与微信小程序中实现多线程的方法,也欢迎大家留言,谢谢!