首页
统计
墙纸
留言
Search
1
PVE8优化
19 阅读
2
mysql创建数据库
12 阅读
3
jenkins根据分支、文件夹打包
12 阅读
4
vue-cli注册全局方法
7 阅读
5
开心的加班
7 阅读
web前端
Vue
CSS
javascript
React
那些年爬过过的坑
ES6
TypeScrippt
ES7
javascript图灵 - 总结
Node
面试总结
React-Native
Web优化
基础
AngularJS
拍摄
Flutter
Dart
Docker
Linux
mysql
PVE
登录
/
注册
Search
标签搜索
vue+elementui
Cicaba
累计撰写
146
篇文章
累计收到
13
条评论
首页
栏目
web前端
Vue
CSS
javascript
React
那些年爬过过的坑
ES6
TypeScrippt
ES7
javascript图灵 - 总结
Node
面试总结
React-Native
Web优化
基础
AngularJS
拍摄
Flutter
Dart
Docker
Linux
mysql
PVE
页面
统计
墙纸
留言
搜索到
6
篇与
的结果
2019-04-01
Web worker
Web workerWeb Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。Web Worker 有以下几个使用注意点。(1)同源限制分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。(2)DOM 限制Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。(3)通信联系Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。(4)脚本限制Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。(5)文件限制Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。基本用法1 主线程主线程采用new命令,调用Worker()构造函数,新建一个 Worker 线程。var worker = new Worker('work.js');Worker()构造函数的参数是一个脚本文件,该文件就是 Worker 线程所要执行的任务。由于 Worker 不能读取本地文件,所以这个脚本必须来自网络。如果下载没有成功(比如404错误),Worker 就会默默地失败。然后,主线程调用worker.postMessage()方法,向 Worker 发消息。worker.postMessage('Hello World');worker.postMessage({method: 'echo', args: ['Work']});worker.postMessage()方法的参数,就是主线程传给 Worker 的数据。它可以是各种数据类型,包括二进制数据。接着,主线程通过worker.onmessage指定监听函数,接收子线程发回来的消息。worker.onmessage = function (event) { console.log('Received message ' + event.data); doSomething(); } function doSomething() { // 执行任务 worker.postMessage('Work done!'); }上面代码中,事件对象的data属性可以获取 Worker 发来的数据。Worker 完成任务以后,主线程就可以把它关掉。worker.terminate();2 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);除了使用self.addEventListener()指定监听函数,也可以使用self.onmessage指定。监听函数的参数是一个事件对象,它的data属性包含主线程发来的数据。self.postMessage()方法用来向主线程发送消息。根据主线程发来的数据,Worker 线程可以调用不同的方法,下面是一个例子。self.addEventListener('message', function (e) { var data = e.data; switch (data.cmd) { case 'start': self.postMessage('WORKER STARTED: ' + data.msg); break; case 'stop': self.postMessage('WORKER STOPPED: ' + data.msg); self.close(); // Terminates the worker. break; default: self.postMessage('Unknown command: ' + data.msg); }; }, false);上面代码中,self.close()用于在 Worker 内部关闭自身。3 Worker 加载脚本Worker 内部如果要加载其他脚本,有一个专门的方法importScripts()。importScripts('script1.js');该方法可以同时加载多个脚本。importScripts('script1.js', 'script2.js');4 错误处理主线程可以监听 Worker 是否发生错误。如果发生错误,Worker 会触发主线程的error事件。worker.onerror(function (event) { console.log([ 'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message ].join('')); });// 或者worker.addEventListener('error', function (event) { // ...});Worker 内部也可以监听error事件。5 关闭 Worker使用完毕,为了节省系统资源,必须关闭 Worker。// 主线程worker.terminate();// Worker 线程self.close();API1 主线程浏览器原生提供Worker()构造函数,用来供主线程生成 Worker 线程。var myWorker = new Worker(jsUrl, options);Worker()构造函数,可以接受两个参数。第一个参数是脚本的网址(必须遵守同源政策),该参数是必需的,且只能加载 JS 脚本,否则会报错。第二个参数是配置对象,该对象可选。它的一个作用就是指定 Worker 的名称,用来区分多个 Worker 线程。// 主线程var myWorker = new Worker('worker.js', { name : 'myWorker' });// Worker 线程self.name // myWorkerWorker()构造函数返回一个 Worker 线程对象,用来供主线程操作 Worker。Worker 线程对象的属性和方法如下。Worker.onerror:指定 error 事件的监听函数。Worker.onmessage:指定 message 事件的监听函数,发送过来的数据在Event.data属性中。Worker.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。Worker.postMessage():向 Worker 线程发送消息。Worker.terminate():立即终止 Worker 线程。2 Worker 线程Web Worker 有自己的全局对象,不是主线程的window,而是一个专门为 Worker 定制的全局对象。因此定义在window上面的对象和方法不是全部都可以使用。Worker 线程有一些自己的全局属性和方法。self.name: Worker 的名字。该属性只读,由构造函数指定。self.onmessage:指定message事件的监听函数。self.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。self.close():关闭 Worker 线程。self.postMessage():向产生这个 Worker 线程发送消息。self.importScripts():加载 JS 脚本。实例:Worker 线程完成轮询有时,浏览器需要轮询服务器状态,以便第一时间得知状态改变。这个工作可以放在 Worker 里面。function createWorker(f) { var blob = new Blob(['(' + f.toString() +')()']); var url = window.URL.createObjectURL(blob); var worker = new Worker(url); return worker; } var pollingWorker = createWorker(function (e) { var cache; function compare(new, old) { ... }; setInterval(function () { fetch('/my-api-endpoint').then(function (res) { var data = res.json(); if (!compare(data, cache)) { cache = data; self.postMessage(data); } }) }, 1000) }); pollingWorker.onmessage = function () { // render data } pollingWorker.postMessage('init');上面代码中,Worker 每秒钟轮询一次数据,然后跟缓存做比较。如果不一致,就说明服务端有了新的变化,因此就要通知主线程。
2019年04月01日
1 阅读
0 评论
0 点赞
2018-11-12
script标签加载
阻塞式脚本每一个script标签,下载和执行都会阻塞页面的渲染.多个script标签加载, 会依次下载执行,后者都必须等待前者下载并执行.非阻塞式脚本延迟脚本加载在HTML4中script标签扩展了也defer属性, 该属性以支持主流浏览器. 有defer属性的script标签,会在浏览器解析到script标签时开始下载, 不会立即执行.会在月面加载完成后执行.即window.onload事件处理之前被执行.asyncasync="async":脚本相对于页面的其余部分异步地执行(当页面继续进行解析时,脚本将被执行)动态加载script既使用dom操作在页面动态添加script标签. 建议添加在页面的head标签里(这样更为安全, ie在body为加载完时, 可能会抛出一个"操作终止"的错误信息),在script标签添加到页面时开始下载并且执行.不会阻塞页面.在script标签接收完成时会触发一个onload事件,IE着为onreadystatechange(用script.readyState判断不同阶段.主要使用loaded,complete判断)var loadScript = function(url,callback){ var script = document.createElement('script'); script.type = "text/javascript"; if(script.readyState){//IE script.onreadystatechange = function(){ if(script.readyState == 'loaded' || script.readyState == 'complete'){ script.onreadystatechange = nuul;//阻止重复调用 callback(); } } }else{ script.onload = function(){ callback(); } } script.src = url; document.getElementByTagName('head')[0].appendChild(script) }
2018年11月12日
2 阅读
0 评论
0 点赞
2018-04-12
Objict属性操作
属性的描述Object.defineProperty(..)修改或新增对象的属性的描述.let Obj = {}; Object.defineProperty(Obj,a,{ value:2, writable:true,//可写 enumerable:true,//可枚举 configurable:true//可配置(值为false时对象属性将不可删除,writable可以从true改为false) })禁止扩展Object.preventExtensions();禁止添加新属性.密封及不能添加也不能删除对象属性.Object.seal();冻结及不可修改,不可添加,不可新增属性.Object.freeze();如果这个对象引用了其他对象, freeze不会生效.“深度冻结”一个对象,具体方法为,首先在这个对象上调用 Object.freeze(..),然后遍历它引用的所有对象并在这些对象上调用 Object.freeze(..)。但是一定要小心,因为这样做有可能会在无意中冻结其他(共享)对象。in 操作符和hasOwnProperty()in 检查对象属性是否在对象及prototype中.hasOwnProperty 检查对象属性是否在对象不检查原型链. var Obj = {}; (a in Obj)//false Obj.hasOwnProperty('a')//false
2018年04月12日
2 阅读
0 评论
0 点赞
2018-03-12
作用域和闭包的深入理解
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。我来对这个定义进行解释下 函数要在执行后不被垃圾回收机制回收,并且可以访问当前作用域中的属性和方法. 函数在当前作用域外也可以被调用!let message = "Cicaba" function foo(){ console.log(message) //是一个 RHS 引用查询 } foo()//Cicaba上面代码并不是真正意义上的闭包.函数内部作用域只是引用了函数外部作用域的变量.(只是作用域链的一种体现)function foo() { var a = 2; function baz() { console.log( a ); // 2 } bar( baz ); } function bar(fn) { fn(); // 妈妈快看呀,这就是闭包! }闭包和作用域链有着密切的关系.闭包就是突破作用域链的一种方式!看一个金典的例子:for(var i = 0; i<6; i++){ setTimeout(function timer(){ console.log(i) },1000) }上面代码每隔一秒会输出6个5,为什么乐?要理解这个问题必须你先理解词法作用域(作用域)我们来看上面代码发生了什么.for循环中定义了一个全局变量i, 每次循环都在改变i的值.而setTimeout是在循环结束后才被执行(延迟回调函数(异步执行)).每次循环都在当前作用域声明一个定时器函数, 都共享一个作用域里的资源, 所以打印了6个5.解决办法for(var i = 0; i<6; i++){ let j = i; setTimeout(function timer(){ console.log(j) },1000) }解决思路在每次循环中创建一个词法作用域,for(let i = 0; i<6; i++){ setTimeout(function timer(){ console.log(i) },1000) } //for循环的let声明, 会有一个特殊的行为, 会在每次循环迭代时重新声明, 并且会把上次迭代的值初始化当前变量!
2018年03月12日
4 阅读
0 评论
0 点赞
2018-03-07
javascript 提升总结
javascript在执行时会经历两个阶段.编译阶段.执行阶段.在编译阶段, 变量申明和函数申明, 都会提升到当前作用域的顶部,注意:函数提升优先于变量提升.函数表达式不会被提升. (具名表达式函数也不会被提升).函数标识符和变量标识符重名时, 变量声明将会被忽略.在普通块中函数声明, 将会被提升到所在的作用域顶部.foo(); // "b" var a = true; if (a) { function foo() { console.log("a"); } } else { function foo() { console.log("b"); } }
2018年03月07日
3 阅读
0 评论
0 点赞
2018-03-07
作用域 - 总结
函数是 JavaScript 中最常见的作用域单元。本质上,声明在一个函数内部的变量或函数会在所处的作用域中“隐藏”起来,这是有意为之的良好软件的设计原则。但函数不是唯一的作用域单元。块作用域指的是变量和函数不仅可以属于所处的作用域,也可以属于某个代码块(通常指 { .. } 内部)。从 ES3 开始,try/catch 结构在 catch 分句中具有块作用域。在 ES6 中引入了 let 关键字(var 关键字的表亲),用来在任意代码块中声明变量。if(..) { let a = 2; } 会声明一个劫持了 if 的 { .. } 块的变量,并且将变量添加到这个块中。let 声明不会再在块级作用域中进行提升.{ //{}可以创建块及作用域 console.log( bar ); // ReferenceError! let bar = 2; }
2018年03月07日
5 阅读
0 评论
0 点赞