学习webworker

1. 什么是webworker

理论多代码少的一个新特性

MDN是这样说的

Web WorkerWeb内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面

一个worker是使用一个构造函数创建的一个对象(e.g. Worker()) 运行一个命名的JavaScript文件

这个文件包含将在工作线程中运行的代码;

workers 运行在另一个全局上下文中,不同于当前的window

因此,使用 window快捷方式获取当前全局的范围 (而不是self) 在一个 Worker 内将返回错误

可以这样理解:

  1. 创建Worker时,JS引擎向浏览器申请开一个子线程(子线程是浏览器开的,完全受主线程控制,而且不能操作DOM
  2. JS引擎线程与worker线程间通过特定的方式通信(postMessage API,需要通过序列化对象来与线程交互特定的数据)

如果有非常耗时的cpu密集型工作,可以单独开一个Worker线程,因为里面不管如何翻天覆地都不会影响JS引擎主线程,
只待计算出结果后,将结果通信给主线程即可

而且注意下,JS引擎是单线程的,这一点的本质仍然未改变,Worker可以理解是浏览器给JS引擎开的外挂,专门用来解决那些大量计算问题。

2. webworker帮助我们解决了什么问题,该如何去使用webworker呢

一些非常耗时的工作会阻塞js的代码,这种情况就需要使用这个东西。
非常耗时的cpu密集型工作!!!

举个例子:我们在两个button中间加一段耗时的script代码。

	<body>
	  <button>111</button>
	  <script src="./1.js"></script>
	  <button>222</button>
	</body>

1.js的耗时代码:

	var start = new Date().getTime()
	
	do {
	  var end = new Date().getTime();
	} while (end - start < 3000)
	console.log("5秒执行结束");

这里我们一般不这样写代码,但是确实一个很好的线程阻塞的问题,因为js的单线程,浏览器的渲染引擎将第一个button渲染结束的时候,执行了script脚本,cpu被js引擎占用,如果这个耗时操作不结束,渲染引擎将无法继续工作,导致页面不能正常的工作。

A. 开启worker

我们这个时候开启一个Worker即可解决这个问题。(注意这个不能读取本地的js文件,否则会报错,只能是服务端的js脚本文件)

	<body>
	  <button>111</button>
	  <script>
	    // 创建新的线程执行05.js
	    var worker= new Worker("./1.js")
	  </script>
	  <button>222</button>
	</body>

只是执行代码还是有些单薄的,我们还需要实现主线程与worker线程之间的通讯

B. 主线程 -> worker线程

主线程调用worker.postMessage()方法,向 Worker 发消息

	worker.postMessage('Hello World');
	worker.postMessage({method: 'echo', args: ['Work']});

主线程通过worker.onmessage指定监听函数,接收子线程发回来的消息。

	worker.onmessage = function (event) {
	  console.log('Received message ' + event.data);
	  doSomething();
	}
	
	function doSomething() {
	  // 执行任务
	  worker.postMessage('Work done!');
	}

Worker 完成任务以后,主线程就可以把它关掉

	worker.terminate();

填坑举例:这个监听一般都是异步的所以我们在主线程关闭的时候要在onmessage中将数据处理完成之后关闭。

    // 创建新的线程执行05.js
    var worker = new Worker("./1.js")

    // 向worker发数据
    worker.postMessage("123")

    // 接收worker的数据
    worker.onmessage = function(event) {
      console.log("主Received message:" + event.data);
      wworkerterminate();
    }
    // w.terminate(); // 消息无法正常的传递,我们在传递前就关掉了
C. worker线程 -> 主线程

Worker 线程内部需要有一个监听函数,监听message事件,监听从主线程来的消息

	self.addEventListener('message', function (e) {
	  self.postMessage('You said: ' + e.data);
	}, false);

上面代码中,self代表子线程自身,即子线程的全局对象。因此,等同于下面两种写法。

	// 写法一
	this.addEventListener('message', function (e) {
	  this.postMessage('You said: ' + e.data);
	}, false);
	
	// 写法二
	addEventListener('message', function (e) {
	  postMessage('You said: ' + e.data);
	}, false);

子线程调用worker.postMessage()方法,向 主线程发消息

  postMessage("456")

子线程接收主线程的消息,并且发送给主线程结果,然后关闭自己

	onmessage = function(event) {
	  console.log("新Received message:" + event.data);
	  postMessage("456")
	  self.close()
	}

子线程关闭自己

	self.close();
D. 关闭 Worker

使用完毕,为了节省系统资源,必须关闭 Worker。

	// 主线程
	worker.terminate();
	
	// Worker 线程
	self.close();

以上就已经完成了worker最基本的使用了。

还在阮一峰老师的博客上看到其他的两个方法在这里搬运一下

1. 在 Worker 内加载脚本

Worker 内部如果要加载其他脚本,有一个专门的方法importScripts()。

	importScripts('script1.js');

该方法可以同时加载多个脚本。

	importScripts('script1.js', 'script2.js');
2. 错误处理

主线程可以监听 Worker 是否发生错误。如果发生错误,Worker 会触发主线程的error事件。

	worker.onerror(function (e) {
	  console.log([
	    'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
	  ].join(''));
	});
	
	// 或者
	worker.addEventListener('error', function (e) {
	  // ...
	});

到这里,最基本的webworker的使用就结束了,希望大家能有所收获。

参考文档:
进程线程:https://segmentfault.com/a/1190000012925872
阮一峰:https://www.ruanyifeng.com/blog/2018/07/web-worker.html

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值