文章目录

  • 突破单线程的瓶颈WEB WORKERS
    • 兼容性
    • 私有worker
      • “杀死”workers
      • 错误调试
      • 异步在worker的表现
    • 共享的shareWorkers
  • service worker
    • 使用
    • 注册一个service worker
    • 使用servers worker
      • 设置缓存和缓存数据
      • 使用缓存
      • 小结
  • 参考文献

突破单线程的瓶颈WEB WORKERS

web worker就是一个后台执行JS文件的方法,能够给前端传递信息,前端也可以传递信息给web wokers.

  • web workers是一个全新的上下文,与创建它的线程无关。
  • 不可以执行dom操作
  • 没有window这个对象
  • 通过postMessage传递消息

兼容性

if (window.Worker) {// 是否可以使用workers...}

私有worker

index.js

if (window.Worker) {var myWoker = new Worker('./work.js')myWoker.postMessage('send message');myWoker.onmessage = function(e) {console.log('Message received from worker',e.data);}
}

work.js

onmessage = function(e) {console.log('Message received from main script');this.console.log(e.data)console.log('Posting message back to main script');postMessage('I get');
}

输出情况

使用web workers还是比较简单的。

  1. 对于使用worker的线程而言:
    首先就是先注册一个workersnew Worker('path')
    然后可以发送数据了
    如果需要接受worker返回的数据,就需要注册一个监听事件onmessage
  2. 对于work.js而言
    首先需要写好一个监听数据请求的事件,当然也可以不用监听直接写好执行数据,这里就看需求。
    如果设置了监听事件,第一个参数会包含发送过来的数据:如实例中的e.data
    当然,worker也可以使用postMessage主动的发送信息给主线程。

“杀死”workers

不想要workers怎么办?直接停掉它。terminate()
myWorker.terminate();
当然,如果workers不想干活了,也可以“罢工”
直接执行这个函数close();即可

错误调试

你当然可以 给workers添加错误回调,如监听数据接受的事件一样,只需要在worker设置好监听即可。

onerror = function(e) {e.message// 错误事件e.filename// 错误文件e.lineno // 错误行号
}

异步在worker的表现

onmessage = function(e) {var a=function ()  {postMessage('I get'+new Date());setTimeout(a, 1000);}setTimeout(a, 1000);
}


我们给主线程也添加异步事件。

var a1 = function ()  {console.log('主线程'+new Date());setTimeout(a1, 2000);
}
if (window.Worker) {var myWoker = new Worker('./work.js')myWoker.postMessage('send message');myWoker.onmessage = function(e) {console.log('Message received from worker',e.data);}setTimeout(a1, 2000);
}


符合多线程的表现,我们弄的复杂点,让主线程的执行超过1秒,看看是否会阻塞workers。
我们在主线程中添加了一个超过一秒的复杂运算,执行之后的情况如下。

首先说下workers,主线程的阻塞并不会影响workers的异步执行,只是会影响它的输出,因为它是通过发送消息给主线程输出的,所以会等主线程执行完,才会按照顺序执行workers 返回的事件队列。
对于主线程而言,阻塞已经影响到了异步了,因为每一次输出已经超过2秒
其实如果workers也有复杂的运算,表现也是和主线程一样的。

这里也可以看出来为什么workers不能操作DOM。
如果workers可以操作DOM的,那么很容易无法更新到最新的状态。

共享的shareWorkers

共享workers,页面之间需要符合同源策略。
index.js

if (!!window.SharedWorker) {var myWorker = new SharedWorker("work.js");myWorker.port.onmessage = function(e) {console.log('Message received from worker');}
}

和workes的区别在于多一个端口调用。
必须设置一个onmessage或者port.start()

什么时候使用start?
当我们需要addEventListener()时候
如何使用?
父页面直接执行 myWorker.port.start()
workers执行 port.start()完成打开端口即可

这是为了与后续的work.js的connect相呼应,因为相当于注册一个端口。
在workers是隐性的,并不是必需进行这步。
如果使用start打开端口,就需要在work.js中调用相同的方法。port.start()

我们来看看work.js的代码

var clients = [];
onconnect = function(e) {var port = e.ports[0];clients.push(port);port.onmessage=function(e) {clients.forEach((item,i)=>{item.postMessage(e.data)})}
}

这里不在是onmessage来设置监听事件了,我们使用一个变量,将所有的注册端口保存起来,这就是共享的意义,一个worker相当于一个单例,所以页面访问的是同一个上下文。
如果想要广播所有端口,就可以像例子中遍历端口发送数据。
如果你需要对某个特定的页面端口进行特别处理,你可以通过父页面的传递信息约定一个数据,进行判断处理事件。
注意:需要页面是同源的情况下才能访问。

service worker

Service worker是一个注册在指定源和路径下的事件驱动worker。
它采用JavaScript控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。
常见于网络不可用的情况下

·service worker同样是workers的另一个类型。但是由于目前支持度不是很高,所以还是遇到很大的兼容性的问题,得不到广泛的使用。

  • 同步API(如XHR和localStorage)不能在service worker中使用。
  • 出于安全考量,Service workers只能由·HTTPS承载

如果一个网页没有了网络,那就将失去所有意义。
所以为了解决这个问题,就需要一个线程脚本,在没有网络连接的时候来控制网页。这样就导致离线页面和service worker的出现。有了这一功能,也代表着网页APP有了与原生APP叫板的底气。

  • 缺点:非常明显,开启service worker可能会导致浏览器的缓存数据大大增加。

使用

生命周期:

  1. 下载
  2. 安装
  3. 激活

用户首次访问service works控制的网站和网址的时候,service works会立刻下载。

之后每24小时就会被下载以此,期间可能频繁更新,不过每24小时一定会被下载一次,以避免不良脚本长时间生效。

如果这是首次启用service worker,页面会首先尝试安装,安装成功后它会被激活。

如果新版本的service worker已经下载完但是正在安装,但是不会被激活,这个时候称为 worker in waiting。
直到所有已经加载页面不再使用旧的service worker 的时候,才会激活新的service worker。新激活的service worker称为active worker

注册一个service worker

·'/sw-test/'·,表示 app 的 origin 下的所有内容。如果你留空的话,默认值也是这个值, 我们在指定只是作为例子。

if ('serviceWorker' in navigator) {// 读取js,进行注册navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {if(reg.installing) {// 这里有判断service worker状态console.log('Service worker installing');} else if(reg.waiting) {console.log('Service worker installed');} else if(reg.active) {console.log('Service worker active');}}).catch(function(error) {// registration failedconsole.log('Registration failed with ' + error);});
}

使用servers worker

设置缓存和缓存数据

进行了上面的注册,就可以开始使用service worker的API了

// sw.jsself.addEventListener('install', function(event) {event.waitUntil(caches.open('v1').then(function(cache) {return cache.addAll(['/sw-test/','/sw-test/index.html','/sw-test/style.css','/sw-test/app.js','/sw-test/image-list.js','/sw-test/star-wars-logo.jpg','/sw-test/gallery/bountyHunters.jpg','/sw-test/gallery/myLittleVader.jpg','/sw-test/gallery/snowTroopers.jpg']);}));
});

我们先讨论首次加载的情况
这里添加的是安装的监听事件。
waitUntil是确保service worker安装前,读取到所有的数据。
caches.open()方法,是创建一个缓存v1区域,保存下面的文件。这里使用的是promise来实现。
service worker安装完成之后,就开始变成激活状态。
虽然都是缓存,但是service worker不允许使用localstorage

使用缓存

添加fetch事件,进行操作。

self.addEventListener('fetch', function(event) {event.respondWith(caches.match(event.request).then(function(response) {// caches.match() always resolves// but in case of success response will have valueif (response !== undefined) {return response;} else {return fetch(event.request).then(function (response) {// response may be used only once// we need to save clone to put one copy in cache// and serve second onelet responseClone = response.clone();caches.open('v1').then(function (cache) {cache.put(event.request, responseClone);});return response;}).catch(function () {return caches.match('/sw-test/gallery/myLittleVader.jpg');});}}));
});

当service worker控制的资源被请求时候,就会触发fetch事件。这些资源包含了指定的scope文档。
事件上的EVENT上的respondWith劫持HTTPS的请求,劫持之后你就可以进行任何的操作
例子中caches.match是用于匹配本地资源是否存在这个文件。
然后判断本地缓存是否有网络请求的响应报文,如果有则使用本地资源缓存,如果没有则使用fetch进行请求,当然也可以使用xht,如果使用后者,你还需要配置路径和方法,而fetch是封装好的API,只需要传入请求文段即可发送请求。
fetch这个方法本身是支持promise的,所以是异步进行请求的。
如果想要下次不需要网络请求,你可以将请求报文段保存到缓存,这样下次请求能够直接使用本地的缓存文件了。
最后如果不出意外,请求会返回一些数据,你可以将他们保存到本地,然后再返回给客户端。
cache.put(event.request, responseClone);

小结

其实service worker更新一个中间代理服务器。它特别的地方是离线状态也可以访问,如果存在你需要的资源就可以返回给你,这样达到离线访问web app的目的。
当然,这种API自然对资源管理要求更加严格,如果滥用很可能会导致缓存过大,打开一个网页会让计算机占的内存变大等问题。目前支持度主要是谷歌的CHROM 和火狐的FIRFOX。这些都是默认关闭的,需要用户自己打开才能使用这个API,所以目前还处在测试的环节。
不过抛开这些短板来看,web app或许真的可能会代替native app。

  • 应用场景

    1. 响应推送:启动一个service work,获取服务器推送的消息,不会影响用户体验
    2. 后台同步:启动一个service work,更新服务器的数据,不会影响用户体验
    3. 自定义模板用于特定URL模式:因为service worker能够劫持HTTP请求,所以可以自己自定义格式进行处理。
    4. 性能增强:我们可以对用户的预处理进行预请求,比如图片的懒加载,可以先使用service worker保存前几页的数据,这样用户交互的时候,就会减少等待时间。

其实上面的功能,普通的web workers都可以实现,但是由于service work已经封装好了API,如劫持HTTP请求的方法,对上面的场景实现起来非常方便。

参考文献

MDN WEB WORKERS

前端开发的workers——web workers、share workers和service workers相关推荐

  1. php前端开发培训,杭州web前端培训技术学校(web前端开发和php开发)

    杭州web前端培训技术学校,选择的时候请记住杭州web前端培训中的web前端框架,web前端开发和ui设计,web前端开发和php开发,web前端开发好不好,学历低能否学习web前端,web适用那些人 ...

  2. 2021年web前端开发视频教程,自学web前端开发技术,全套web前端学习路线笔记

    2021年web前端开发视频教程,自学web前端开发技术,全套web前端学习路线笔记 [导读]:初学web前端的小伙伴经常会遇到的问题,1.没方法 2.没资源 3.没经验,不知道从何开始 ,代码哥(D ...

  3. html前端开发是什么,web前端开发需要会什么

    对于很多刚入坑it行业的新人小白来说,web前端开发算是一个对技术要求比较高的岗位,我们经常在一些企业招聘上可以看到web前端的工程师需要掌握多个技能,甚至后端的开发语言都需要掌握一两门,这着实吓坏了 ...

  4. 0基础学习前端开发,高职web前端开发技能大赛

    零基础学web前端开发要怎么去学? 首先要学习的就是基础知识:html.css和JavaScript.HTML是内容,CSS是表现,JavaScript是行为.前端开发的门槛其实非常低,与服务器端语言 ...

  5. Hapi.js 起步 - 写给前端开发的 Node Web 框架入门

    为什么选择 Hapi 或许你已经使用过 Express, Koa2 等 Node.js 的 WEB 框架,在构建 WEB 应用程序时,你的工作仅仅是产出 RESTFUL API,或者通过 Node 调 ...

  6. 前端开发和html5,Web前端和HTML5前端相同吗 有区别吗

    学习web前端和学习HTML5是否一样呢,当前的社会技术更新太快了,小伙伴们都不知道要学习什么专业了.最近有学员咨询说,什么是web前端,什么是HTML5前端,两者之间有什么区别呢? 今天IT培训网小 ...

  7. html5前端开发做什么,Web前端能做什么开发

    对于想要学习HTML5大前端的人来说,从哪里开始入手是困扰他们的难题.前端开发工作已经变的越来越复杂,仅仅是想罗列一份前端开发的学习列表就已经是一件艰巨的工作.曾经只要会编写HTML, CSS和Jav ...

  8. Web前端开发敲门砖 ——《Web前端工程师修炼之道》

    随着多设备.浏览器和Web标准的演变革命,前端正在成为兼顾逻辑.性能.交互.体验的综合性岗位. 前端开发入门又相对容易,必须掌握的HTML+CSS+JS非常容易学习,如果你能再了解一定后端知识,对业务 ...

  9. html前端开发学年论文,web前端毕业设计论文.doc

    web前端毕业设计论文 毕 业 论 文 题目:响应式企业网站设计与实现学生姓名:罗智刚学号:1202012132专业班级:B12计算机科学与技术2班指导教师:李莉企业导师:林志宏二级学院:电气与信息工 ...

  10. 前端开发人员必备Web前端面试题与答案 西安尚学堂

    HTML: 1.对WEB标准以及W3C的理解与认识 标签闭合.标签小写.不乱嵌套.提高搜索机器人搜索几率.使用外 链css和js脚本.结构行为表现的分离.文件下载与页面速度更快.内容能被更多的用户所访 ...

最新文章

  1. Linux/windows系统定时任务调度总结
  2. python opencv手册_教你用Python实现5毛钱特效(给你的视频来点料)
  3. RCC 2017 Qual 1 Mail.Ru, April 2, 2017 Problem B. Painting the Wall
  4. (王道408考研操作系统)第二章进程管理-第三节4:信号量机制(整型、记录型信号量和P、V操作)
  5. php web 简单的系统,Slim 简单而强大的 PHP 微型 Web 开发框架 - 资源分享
  6. Zookeeper基础使用
  7. openstack mitaka 完整安装详细文档(亲测,花了3天时间)
  8. java实现活动安排问题_贪心算法-活动安排问题
  9. HFSS - 圆形双馈微带天线
  10. 并发测试工具Jmeter安装与简单使用
  11. Chrome 扩展程序 CrxMouse Techzero优化版 更新至 v3.0.4
  12. 统计遗传学:第五章,多基因评分PGS
  13. Win10查看电脑的开机时间和关机时间记录
  14. 全文翻译 | 华为、北大、悉尼大学:最新视觉Transformer综述(2017-2020年)
  15. 高德地图WEB端,在所画的圆(Circle)内显示在圆(Marker)内的点
  16. C语言实现贪吃蛇小游戏(详解)
  17. pandas中的滚动窗口rolling函数和扩展窗口expanding函数
  18. 钙钛矿Cs2AgBiBr6|三氟乙胺碘F3EAI|4-三氟甲基苯胺溴CF3PhABr
  19. Java 三大器之监听器Listener
  20. 时间戳转换为日期格式 C/C++ 学习日记 新手讲解

热门文章

  1. WinRAR文件分卷压缩具体使用方法图文教程
  2. Mac升级自带PHP版本(非Homebrew方式)
  3. Android uses-permission 权限大全
  4. 用plt.scatter画散点图
  5. 通证网:一建的报考条件
  6. android换肤动画,Android换肤(二) — 插件式换肤
  7. CoBot 库博源代码缺陷检测工具
  8. 群晖 USB存储改内置存储空间 | 玩物下载 到U盘 | 套件安装到U盘
  9. 双向广搜-HDU1401 Solitaire
  10. 玩转华为数据中心交换机系列 | 配置基本QinQ示例