HTML5CORE03
目录
前言
一、复习
二、SVG
三、Echarts
四、Webworker
五、回调地狱
六、Promise
七、promise+ajax
八、promise_axios
九、async_await
总结
前言
HTML5CORE03学习开始
一、复习
跨域
- 浏览器的同源策略限定:
网页中利用 AJAX 请求数据, 必须访问同源的服务器
同源:
协议 端口 域名- 解决方案
- CORS: 服务器解决, 用
cors
模块- PROXY: 代理方案, 用
express-http-proxy
模块- JSONP: 需要服务器和前端共同解决
- 利用脚本的 src 请求数据没有跨域限定
拖拽
- HTML5新增的事件
- 被拖拽的元素
- dragstart: 开始拖拽
- drag : 正在拖拽, 每 350毫秒 触发一次
- dragend :停止拖拽
- 拖拽元素放置的
- dragenter : 进入
- dragleave :离开
- dragover: 在上方
- drop : 放下
- 利用 dataTransfer 属性来传递拖拽的数据
文件上传
- 服务器端
- 利用
multer
模块来接收上传的文件- 前端
- form表单 -- 适合简单的上传
- DOM
- 使用 FormData 来组合上传的数据
- 利用 ajax 请求发送给服务器
canvas
- 利用 JS 实时绘制图表
- 用途: 地图, 页游, 图表...
- 制作时
- 利用 canvas 标签制作一个画布
- 在JS中利用
getContext('2d')
获取画布的工具箱
- fillStyle : 填充色
- strokeStyle : 线的颜色
- fillRect : 填充矩形
- fillText : 文本
- ...
地图
- 百度, 腾讯, 谷歌, 高德...
- 利用 第三方 开放平台提供的资源 来显示地图
- 使用方式:
学会参考官方文档
二、SVG
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>svg 09:12</title> <style> #c1 { height: 100px; } </style> </head> <body> <!-- svg的作用 与 canvas 相同, 都是用于展示图片 --> <!-- canvas: 利用JS 根据数据 实时绘制图片 svg: 利用 DOM元素 来绘制图片 -- 实时绘制, 属于矢量图 - 放大不会降低质量 --> <canvas id="c1" width="200" height="35"></canvas> <p style="font-size: 120px;">Hello World!</p> <!-- 下载地址: https://www.iconfont.cn/ --> <!-- 随意放大缩小, 会被浏览器实时渲染 --> <img src="./bear.svg" height="2000" alt=""> <script> /** @type {HTMLCanvasElement} */ var c1 = document.getElementById('c1') var ctx = c1.getContext('2d') ctx.font = '30px 微软雅黑' ctx.fillText('Hello World!', 0, 30) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>svg 09:31</title> <style> #svg_11 { transition: 0.2s; } #svg_11:hover { fill: aquamarine; } </style> </head> <body> <!-- svg: 利用DOM元素实时生成的图; 特色: 无惧放大缩小 --> <!-- 在线编辑器: https://c.runoob.com/more/svgeditor/ --> <img src="./my.svg" alt="" height="200"> <!-- 由于SVG是DOM方式的, 所以可以利用DOM进行一些操作 --> <svg width="300" height="300" xmlns="http://www.w3.org/2000/svg"> <g id="Layer_1"> <title>Layer 1</title> <text xml:space="preserve" text-anchor="start" font-family="Noto Sans JP" font-size="24" id="svg_1" y="39" x="77.44501" stroke-width="0" stroke="#000" fill="#000000">Hello 亮亮</text> <path stroke="#000" id="svg_7" d="m110.39082,147.46209c-4.30191,-8.00924 -9.565,-14.49356 -14.84424,-19.0296c-6.16005,4.64946 -13.66266,7.48064 -21.84197,7.48064c-8.19536,0 -15.70877,-2.83669 -21.85796,-7.48064c-5.27923,4.53603 -10.5477,11.02035 -14.86017,19.0296c-10.01075,18.59517 -11.11169,37.66907 -2.46521,42.61467c3.87226,2.22784 7.93227,0.56734 12.12672,-3.59787c-0.73576,4.22326 -1.16544,8.80072 -1.16544,13.58862c0,21.27141 8.01826,38.50213 17.8999,38.50213c5.956,0 8.90439,-6.27409 10.32214,-15.88021c1.41252,9.60611 4.36089,15.88021 10.2953,15.88021c9.89788,0 17.91622,-17.23072 17.91622,-38.50213c0,-4.7879 -0.42981,-9.36536 -1.18157,-13.58862c4.20509,4.16521 8.25976,5.82571 12.14277,3.59787c8.64116,-4.94561 7.52397,-24.01951 -2.48651,-42.61467l-0.00001,0zm-36.69678,-18.80544c16.62702,0 30.11241,-13.89856 30.11241,-31.04349s-13.48538,-31.04352 -30.11241,-31.04352c-16.63268,0 -30.12871,13.90133 -30.12871,31.04352s13.49603,31.04349 30.12871,31.04349z" stroke-width="0" fill="#a02b2b" /> <path stroke="#000" id="svg_11" d="m237.95597,168.09433c-5.15842,-8.31914 -11.47678,-15.05219 -17.81131,-19.75922c-7.39132,4.82784 -16.39362,7.76464 -26.21768,7.76464c-9.83034,0 -18.8456,-2.94554 -26.22733,-7.76464c-6.33452,4.70703 -12.65282,11.44008 -17.83067,19.75922c-12.00853,19.30511 -13.33597,39.1101 -2.96429,44.24822c4.64617,2.31322 9.52115,0.58625 14.55393,-3.73574c-0.88607,4.38229 -1.41128,9.1353 -1.41128,14.10956c0,22.08684 9.62098,39.97794 21.48133,39.97794c7.14323,0 10.68429,-6.51727 12.38219,-16.49166c1.69797,9.97439 5.23573,16.49166 12.36302,16.49166c11.87634,0 21.49729,-17.89111 21.49729,-39.97794c0,-4.97426 -0.51547,-9.72726 -1.41761,-14.10956c5.04887,4.322 9.9141,6.04896 14.56989,3.73574c10.38791,-5.13812 9.04424,-24.9431 -2.96749,-44.24822zm-44.03862,-19.52631c19.96048,0 36.14144,-14.43435 36.14144,-32.23362s-16.18096,-32.23352 -36.14144,-32.23352c-19.95727,0 -36.15116,14.43134 -36.15116,32.23352s16.19389,32.23362 36.15116,32.23362zm24.6904,-66.1626c10.42969,3.4254 4.15315,-5.46283 4.15315,-11.53479s6.43764,-13.49747 -4.15315,-10.47721c-11.11601,3.17816 -20.12802,4.92536 -20.12802,11.00593s9.01202,7.35081 20.12802,11.00608zm-24.62272,-4.32479c6.60515,0 2.91593,-2.98284 2.91593,-6.65824c0,-3.67822 3.69888,-6.65249 -2.91593,-6.65249s-3.15763,2.98286 -3.15763,6.65249c0,3.68398 -3.44762,6.65824 3.15763,6.65824zm-24.76452,4.32479c11.11602,-3.64671 20.12795,-4.92833 20.12795,-11.00608s-9.01194,-7.82777 -20.12795,-11.00593c-10.59081,-3.02887 -4.15643,4.39943 -4.15643,10.47721s-6.28295,14.95441 4.15643,11.53479z" stroke-width="0" fill="#a02b2b" /> </g> </svg> <script> // 点击时, 能够变色 // SVG特点: 图片中的内容 可以与用户进行交互 var svg_11 = document.getElementById('svg_11') svg_11.onclick = function () { this.style.fill = 'orange' } svg_11.onmouseover = function () { alert("别碰我 讨厌!") } </script> </body> </html>
三、Echarts
- 官网:Handbook - Apache ECharts
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>echarts 10:17</title> </head> <body> <div id="main" style="width: 600px;height:400px;"></div> <script src="./echarts.min.js"></script> <script> // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('main')); // 指定图表的配置项和数据 // 配置项中的每个属性 都是有固定的作用, 详细要查看使用说明文档 var option = { // 标题 title: { // 文本 text: '大学生就业率' }, tooltip: {}, // 图例 legend: { data: ['就业人数'] }, // x坐标轴上的内容 xAxis: { data: ['北理工', '北师范', '北外', '清华', '北大', '人民大学'] }, // y坐标轴上的内容, 不主动填写 则根据数据自动生成 yAxis: {}, // 具体的 数据系列 series: [ { name: '就业人数', type: 'bar', // 柱状图 data: [13165, 20122, 33336, 44410, 55550, 32120] } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>echarts 10:36</title> <script src="./echarts.min.js"></script> </head> <body> <div id="main" style="width: 600px; height: 500px;"></div> <script> var myChart = echarts.init(main) // 初始化 // 要显示的内容配置 option = { xAxis: { data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] }, yAxis: {}, series: [ { type: 'bar', data: [123, 234, 128, 215, 227, 228, 215] } ] }; myChart.setOption(option) // 载入个性化配置 </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>echarts 10:53</title> <script src="./echarts.min.js"></script> </head> <body> <div id="main" style="width: 1000px; height: 300px;"></div> <script> var myChart = echarts.init(main) option = { xAxis: { data: ['北京', '郑州', '成都', '客村', '深圳', '上海', '石家庄'] }, yAxis: {}, series: [ { type: 'bar', data: [23, 24, 18, 25, 27, 28, 25], itemStyle: { color: 'red' } }, { type: 'bar', data: [26, 24, 18, 22, 23, 20, 27], itemStyle: { color: 'green' } }, { type: 'bar', data: [6, 4, 8, 2, 2, 0, 7], itemStyle: { color: 'blue' } } ] }; myChart.setOption(option) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>堆叠 11:24</title> <script src="./echarts.min.js"></script> </head> <body> <div id="main" style="width: 500px; height: 300px;"></div> <script> var myChart = echarts.init(main) option = { xAxis: { data: ['A', 'B', 'C', 'D', 'E'] }, yAxis: {}, series: [ { data: [10, 22, 28, 43, 49], type: 'bar', stack: 'x', //堆叠 在 x 轴 }, { data: [5, 4, 3, 5, 10], type: 'bar', stack: 'x' } ] }; myChart.setOption(option) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>echarts 11:40</title> </head> <body> <div id="main" style="width: 700px; height: 500px;"> </div> <script src="./echarts.min.js"></script> <script> var myChart = echarts.init(main) // 实际开发时: 加入显示 2000年 - 2022年 的某些数据 // 需要有一个数组, 存储的对应年份的数据 // 通过定时器, 例如 每隔3秒, 读取数组中的1条数据进行展示 // 生成 5个随机数字 var data = []; for (let i = 0; i < 5; ++i) { data.push(Math.round(Math.random() * 200)); } option = { // x轴 xAxis: { // 最大值 max: 'dataMax' }, title: { text: "GDP总值" }, yAxis: { type: 'category', data: ['北京', '上海', '广州', '深圳', '杭州'], inverse: true, animationDuration: 300, animationDurationUpdate: 300, max: 3 }, series: [ { realtimeSort: true, name: 'X', type: 'bar', data: data, label: { show: true, position: 'right', valueAnimation: true } } ], legend: { show: true }, animationDuration: 2000, animationDurationUpdate: 2000, animationEasing: 'linear', animationEasingUpdate: 'linear' }; // 读取配置项中的数据, 遍历之后 随机进行更新 function update() { var data = option.series[0].data; for (var i = 0; i < data.length; ++i) { if (Math.random() > 0.9) { data[i] += Math.round(Math.random() * 2000); } else { data[i] += Math.round(Math.random() * 200); } } myChart.setOption(option) // 更新图表 } // 每隔 3秒 触发一次 update() 方法, 更新数据 setInterval(function () { update(); }, 2000); myChart.setOption(option) </script> </body> </html><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>echarts 11:40</title> </head> <body> <div id="main" style="width: 700px; height: 500px;"> </div> <script src="./echarts.min.js"></script> <script> var myChart = echarts.init(main) // 实际开发时: 加入显示 2000年 - 2022年 的某些数据 // 需要有一个数组, 存储的对应年份的数据 // 通过定时器, 例如 每隔3秒, 读取数组中的1条数据进行展示 // 生成 5个随机数字 var data = []; for (let i = 0; i < 5; ++i) { data.push(Math.round(Math.random() * 200)); } option = { // x轴 xAxis: { // 最大值 max: 'dataMax' }, title: { text: "GDP总值" }, yAxis: { type: 'category', data: ['北京', '上海', '广州', '深圳', '杭州'], inverse: true, animationDuration: 300, animationDurationUpdate: 300, max: 3 }, series: [ { realtimeSort: true, name: 'X', type: 'bar', data: data, label: { show: true, position: 'right', valueAnimation: true } } ], legend: { show: true }, animationDuration: 2000, animationDurationUpdate: 2000, animationEasing: 'linear', animationEasingUpdate: 'linear' }; // 读取配置项中的数据, 遍历之后 随机进行更新 function update() { var data = option.series[0].data; for (var i = 0; i < data.length; ++i) { if (Math.random() > 0.9) { data[i] += Math.round(Math.random() * 2000); } else { data[i] += Math.round(Math.random() * 200); } } myChart.setOption(option) // 更新图表 } // 每隔 3秒 触发一次 update() 方法, 更新数据 setInterval(function () { update(); }, 2000); myChart.setOption(option) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>折线图</title> </head> <body> <div id="main1" style="width: 600px; height: 300px;"></div> <div id="main2" style="width: 600px; height: 300px;"></div> <div id="main3" style="width: 600px; height: 300px;"></div> <script src="./echarts.min.js"></script> <script> var chart1 = echarts.init(main1) chart1.setOption({ xAxis: { type: 'category', data: ['2020', '2021', '2022'] }, yAxis: { type: 'value' }, series: [ { data: [120, 200, 150], type: 'line' } ] }) var chart2 = echarts.init(main2) chart2.setOption({ xAxis: {}, yAxis: {}, series: [ { data: [ [20, 120], [50, 200], [40, 50] ], type: 'line' } ] }) var chart3 = echarts.init(main3) chart3.setOption({ series: [ { type: 'pie', data: [ { value: 335, name: '男性' }, { value: 234, name: '女性' }, { value: 1548, name: '未知' } ] } ] }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>时钟 14:31</title> <style> #main { transform: scale(0.3); /* 缩放时, 按照左上角对齐 */ transform-origin: 0 0; } </style> </head> <body> <div id="main" style="height: 600px"></div> <script src="./echarts.min.js"></script> <script> var myChart = echarts.init(main) option = { series: [ { name: 'hour', type: 'gauge', startAngle: 90, endAngle: -270, min: 0, max: 12, splitNumber: 12, clockwise: true, axisLine: { lineStyle: { width: 15, color: [[1, 'rgba(0,0,0,0.7)']], shadowColor: 'rgba(0, 0, 0, 0.5)', shadowBlur: 15 } }, splitLine: { lineStyle: { shadowColor: 'rgba(0, 0, 0, 0.3)', shadowBlur: 3, shadowOffsetX: 1, shadowOffsetY: 2 } }, axisLabel: { fontSize: 50, distance: 25, formatter: function (value) { if (value === 0) { return ''; } return value + ''; } }, anchor: { show: true, icon: 'path://M532.8,70.8C532.8,70.8,532.8,70.8,532.8,70.8L532.8,70.8C532.7,70.8,532.8,70.8,532.8,70.8z M456.1,49.6c-2.2-6.2-8.1-10.6-15-10.6h-37.5v10.6h37.5l0,0c2.9,0,5.3,2.4,5.3,5.3c0,2.9-2.4,5.3-5.3,5.3v0h-22.5c-1.5,0.1-3,0.4-4.3,0.9c-4.5,1.6-8.1,5.2-9.7,9.8c-0.6,1.7-0.9,3.4-0.9,5.3v16h10.6v-16l0,0l0,0c0-2.7,2.1-5,4.7-5.3h10.3l10.4,21.2h11.8l-10.4-21.2h0c6.9,0,12.8-4.4,15-10.6c0.6-1.7,0.9-3.5,0.9-5.3C457,53,456.7,51.2,456.1,49.6z M388.9,92.1h11.3L381,39h-3.6h-11.3L346.8,92v0h11.3l3.9-10.7h7.3h7.7l3.9-10.6h-7.7h-7.3l7.7-21.2v0L388.9,92.1z M301,38.9h-10.6v53.1H301V70.8h28.4l3.7-10.6H301V38.9zM333.2,38.9v10.6v10.7v31.9h10.6V38.9H333.2z M249.5,81.4L249.5,81.4L249.5,81.4c-2.9,0-5.3-2.4-5.3-5.3h0V54.9h0l0,0c0-2.9,2.4-5.3,5.3-5.3l0,0l0,0h33.6l3.9-10.6h-37.5c-1.9,0-3.6,0.3-5.3,0.9c-4.5,1.6-8.1,5.2-9.7,9.7c-0.6,1.7-0.9,3.5-0.9,5.3l0,0v21.3c0,1.9,0.3,3.6,0.9,5.3c1.6,4.5,5.2,8.1,9.7,9.7c1.7,0.6,3.5,0.9,5.3,0.9h33.6l3.9-10.6H249.5z M176.8,38.9v10.6h49.6l3.9-10.6H176.8z M192.7,81.4L192.7,81.4L192.7,81.4c-2.9,0-5.3-2.4-5.3-5.3l0,0v-5.3h38.9l3.9-10.6h-53.4v10.6v5.3l0,0c0,1.9,0.3,3.6,0.9,5.3c1.6,4.5,5.2,8.1,9.7,9.7c1.7,0.6,3.4,0.9,5.3,0.9h23.4h10.2l3.9-10.6l0,0H192.7z M460.1,38.9v10.6h21.4v42.5h10.6V49.6h17.5l3.8-10.6H460.1z M541.6,68.2c-0.2,0.1-0.4,0.3-0.7,0.4C541.1,68.4,541.4,68.3,541.6,68.2L541.6,68.2z M554.3,60.2h-21.6v0l0,0c-2.9,0-5.3-2.4-5.3-5.3c0-2.9,2.4-5.3,5.3-5.3l0,0l0,0h33.6l3.8-10.6h-37.5l0,0c-6.9,0-12.8,4.4-15,10.6c-0.6,1.7-0.9,3.5-0.9,5.3c0,1.9,0.3,3.7,0.9,5.3c2.2,6.2,8.1,10.6,15,10.6h21.6l0,0c2.9,0,5.3,2.4,5.3,5.3c0,2.9-2.4,5.3-5.3,5.3l0,0h-37.5v10.6h37.5c6.9,0,12.8-4.4,15-10.6c0.6-1.7,0.9-3.5,0.9-5.3c0-1.9-0.3-3.7-0.9-5.3C567.2,64.6,561.3,60.2,554.3,60.2z', showAbove: false, offsetCenter: [0, '-35%'], size: 120, keepAspect: true, itemStyle: { color: '#707177' } }, pointer: { icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z', width: 12, length: '55%', offsetCenter: [0, '8%'], itemStyle: { color: '#C0911F', shadowColor: 'rgba(0, 0, 0, 0.3)', shadowBlur: 8, shadowOffsetX: 2, shadowOffsetY: 4 } }, detail: { show: false }, title: { offsetCenter: [0, '30%'] }, data: [ { value: 0 } ] }, { name: 'minute', type: 'gauge', startAngle: 90, endAngle: -270, min: 0, max: 60, clockwise: true, axisLine: { show: false }, splitLine: { show: false }, axisTick: { show: false }, axisLabel: { show: false }, pointer: { icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z', width: 8, length: '70%', offsetCenter: [0, '8%'], itemStyle: { color: '#C0911F', shadowColor: 'rgba(0, 0, 0, 0.3)', shadowBlur: 8, shadowOffsetX: 2, shadowOffsetY: 4 } }, anchor: { show: true, size: 20, showAbove: false, itemStyle: { borderWidth: 15, borderColor: '#C0911F', shadowColor: 'rgba(0, 0, 0, 0.3)', shadowBlur: 8, shadowOffsetX: 2, shadowOffsetY: 4 } }, detail: { show: false }, title: { offsetCenter: ['0%', '-40%'] }, data: [ { value: 0 } ] }, { name: 'second', type: 'gauge', startAngle: 90, endAngle: -270, min: 0, max: 60, animationEasingUpdate: 'bounceOut', clockwise: true, axisLine: { show: false }, splitLine: { show: false }, axisTick: { show: false }, axisLabel: { show: false }, pointer: { icon: 'path://M2.9,0.7L2.9,0.7c1.4,0,2.6,1.2,2.6,2.6v115c0,1.4-1.2,2.6-2.6,2.6l0,0c-1.4,0-2.6-1.2-2.6-2.6V3.3C0.3,1.9,1.4,0.7,2.9,0.7z', width: 4, length: '85%', offsetCenter: [0, '8%'], itemStyle: { color: '#C0911F', shadowColor: 'rgba(0, 0, 0, 0.3)', shadowBlur: 8, shadowOffsetX: 2, shadowOffsetY: 4 } }, anchor: { show: true, size: 15, showAbove: true, itemStyle: { color: '#C0911F', shadowColor: 'rgba(0, 0, 0, 0.3)', shadowBlur: 8, shadowOffsetX: 2, shadowOffsetY: 4 } }, detail: { show: false }, title: { offsetCenter: ['0%', '-40%'] }, data: [ { value: 0 } ] } ] }; setInterval(function () { var date = new Date(); var second = date.getSeconds(); var minute = date.getMinutes() + second / 60; var hour = (date.getHours() % 12) + minute / 60; option.animationDurationUpdate = 300; myChart.setOption({ series: [ { name: 'hour', animation: hour !== 0, data: [{ value: hour }] }, { name: 'minute', animation: minute !== 0, data: [{ value: minute }] }, { animation: second !== 0, name: 'second', data: [{ value: second }] } ] }); }, 1000); myChart.setOption(option) </script> </body> </html>
四、Webworker
属于
性能优化
的方案之一
- 如果 JS代码的执行 特别耗时, 可以用
Worker
对象执行. 类似异步
操作 不会阻塞主线程- 有两种用法
- 用法1: 直接
new Worker(js文件)
执行即可- 用法2: 依赖
postMessage
和onmessage
来实现消息的互通<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webworker 14:40</title> </head> <body> <!-- 浏览器提供了 webworker 功能, 模拟多线程操作, 执行耗时的任务 --> <p id="p1"></p> <button id="btn1">执行耗时操作</button> <script> const btn1 = document.getElementById('btn1') btn1.onclick = function () { // 网页假死: 网页属于单线程操作, 同一时间只能完成一个 JS 代码 // fb() 函数执行完成前, 处于锁死状态 // var x = fb(45) // console.log('x:', x) // 利用 webworker 来运行 10.js 文件中的代码 // // 之前: 自己下楼买东西, 耗时半个小时 -- 无法做其他工作 // 现在 相当于 找了个 美团跑腿 帮你做事 new Worker('./10.js') // new Worker(): 创建一个 工人 对象, 去执行 js 代码 } // 斐波那契数列 -- 很耗时 function fb(n) { return n < 3 ? 1 : fb(n - 1) + fb(n - 2) } const p1 = document.getElementById('p1') setInterval(() => { p1.innerHTML = new Date().toLocaleTimeString() }, 1000); </script> </body> </html>
// 10.js function fb(n) { return n < 3 ? 1 : fb(n - 1) + fb(n - 2) } console.log('请稍后, 一个工人已经在工作...'); var x = fb(45) console.log('x:', x)
- 信息交互
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webworker 15:16</title> </head> <body> <!-- webworker的通信 --> <!-- 需求: 制作一个worker 去执行耗时的 js 文件, 执行完毕后需要提供反馈 --> <p id="p1"></p> <button id="btn1">给骑手发消息点餐</button> <script> const btn1 = document.getElementById('btn1') const p1 = document.getElementById('p1') btn1.onclick = function () { var worker = new Worker('./11.js') //召唤1个骑手 // 给骑手发消息: 消息内容自定义 worker.postMessage({ name: "疯狂星期四 KFC", tips: '原味炸鸡, 汉堡, 冰可乐', address: "北京市海淀区万寿路文博大厦达内教育" }) // 接收消息 worker.onmessage = function (e) { console.log('来自骑手的消息:', e) p1.innerHTML = e.data.x + JSON.stringify(e.data.data) } } </script> </body> </html>
// 11.js function fb(n) { return n < 3 ? 1 : fb(n - 1) + fb(n - 2) } // 发消息: postMessage -- post 传递 传输 // 听消息: onmessage -- on 当...时 // 当前文件 -- 外卖骑手: 听有没有人点餐 onmessage = function (e) { console.log('骑手收到消息:', e) console.log('正在取餐中..., 请稍后'); // 开始耗时操作 var x = fb(45) // 发消息给用户 postMessage({ x, data: e.data }) }
五、回调地狱
- 当出现多个 回调函数嵌套时, 代码的结构会出现层层嵌套的情况, 不易读 不易维护
- 来自 ES6 的 Promise 可以解决 回调地狱
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>回调地狱 15:52</title> </head> <body> <script> // 任务: 一个注册页面 // 当点击提交注册按钮后 -- 先后发请求检查 // 1. 用户名是否重复 // 2. 手机号是否已存在 // 3. 邮箱是否已注册 // 4. 完成注册操作 // 假设返回值中的code 是200 代表正确 $.get('验证用户名', data => { if (data.code == 200) { $.get('验证手机号', data => { if (data.code == 200) { $.get('验证邮箱', data => { if (data.code == 200) { $.post('注册用户', {}, data => { if (data.code == 200) { alert("注册成功") } else { alert("注册失败!") } }) } else { alert("邮箱已存在!") } }) } else { alert("手机号已存在!") } }) } else { alert("用户名已存在!") } }) </script> </body> </html>
六、Promise
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise 16:17</title> </head> <body> <!-- Promise: ES6中提出的新的构造函数, 提供了链式语法 来完成异步操作 --> <!-- 可以回调函数 带来的 回调地狱问题 --> <script> // 固定的语法格式, 背下来即可 new Promise((resolve, reject) => { // resolve: 解决 -- 调用后触发 then 中的箭头函数 // resolve("我是resolve") // reject: 拒绝 -- 调用后触发 catch 中的箭头函数 reject('我是reject') }) .then(res => { // then: 然后 console.log('res', res); }) .catch(err => { // catch: 抓取 console.log('err:', err) }) </script> </body> </html>
七、promise+ajax
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Promise+Ajax 16:37</title> </head> <body> <!-- Promise出现的目的: 用于解决回调地狱 --> <!-- 回调地狱 就是异步操作导致 -- 最常见AJAX网络请求 --> <script> new Promise((resolve, reject) => { var url = 'https://api.xin88.top/game/heros.json' var xhr = new XMLHttpRequest() xhr.open('get', url) xhr.onload = function () { var data = JSON.parse(xhr.response) // console.log(data); // 请求成功后, 利用 resolve 传递数据 resolve(data) } xhr.send() }) .then(res => { console.log('res', res); }) .catch(err => console.log(err)) </script> </body> </html>
八、promise_axios
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>promise_axios 17:01</title> </head> <body> <!-- axios: 这是一款用 promise 封装后得到的 ajax请求库 --> <!-- 非常有名, 下个阶段会使用到 --> <!-- 此处 模拟 封装一个axios --> <script> const axios = { get(url) { // prom return new Promise((resolve, reject) => { var xhr = new XMLHttpRequest() xhr.open('get', url) xhr.onload = function () { resolve(JSON.parse(xhr.response)) } xhr.send() }); } } // 使用时: // get() 的返回值是 new Promise() // 所以这个代码相当于 new Promise().then() var url1 = 'https://api.xin88.top/car/news.json' var url2 = 'https://api.xin88.top/game/heros.json' var url3 = 'https://api.xin88.top/douban/movies.json' var url4 = 'https://api.xin88.top/douban/songlist.json' axios.get(url1).then(res => { console.log('res1:', res) // 请求 url2 的数据 // Promise解决回调地狱的 精髓: 返回值会触发下一个 then - 然后 return axios.get(url2) }).then(res => { console.log('res2:', res); return axios.get(url3) }).then(res => { console.log('res3:', res) return axios.get(url4) }).then(res => { console.log('res4:', res); }) </script> </body> </html>
九、async_await
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>async_await 17:47</title> </head> <body> <script> const axios = { get(url) { // prom return new Promise((resolve, reject) => { var xhr = new XMLHttpRequest() xhr.open('get', url) xhr.onload = function () { resolve(JSON.parse(xhr.response)) } xhr.send() }); } } var url1 = 'https://api.xin88.top/car/news.json' var url2 = 'https://api.xin88.top/game/heros.json' var url3 = 'https://api.xin88.top/douban/movies.json' var url4 = 'https://api.xin88.top/douban/songlist.json' // ES6提供的语法糖: 解决用 then 不适应者.. // async: 异步的 -- 代表这个函数中的所有代码 都要异步执行 // await: 等待 -- 等待这行代码执行完毕 再执行下一行 // 采用 await 语法糖, 则函数必须带有 async 标识 async function getData() { // await: 代表把 then 转换成 返回值模式 var res1 = await axios.get(url1) console.log('res1:', res1) var res2 = await axios.get(url2) console.log('res2:', res2) var res3 = await axios.get(url3) console.log('res3:', res3); var res4 = await axios.get(url4) console.log("res4:", res4); } getData() </script> </body> </html>
总结
HTML5CORE03学习结束