一.同步与异步 1. Promise作用:解决异步回调的问题 二.Promise对象 目的:创建异步对象,当异步对象中的异步操作执行完之后,再执行想要执行的东西。 1. resolve 表示将状态变成成功完成,reject 表示将状态变成失败完成。 2. 当resolve方法执行完成之后,再执行then方法。
1 2 3 4 5 6 7 8 9 10 |
let p = new Promise((resolve,reject)=>{ setTimeout(()=>{ console.log('执行完毕!'); resolve(); //表示完成 },3000) }); p.then(()=>{ console.log('promise异步操作完成了'); }); |
三.Promise传参 resolve里的参数可以传给then
1 2 3 4 5 6 7 8 9 10 |
let p = new Promise((resolve,reject)=>{ setTimeout(()=>{ //console.log('脱完衣服'); resolve(3); },3000) }); p.then((d)=>{ console.log('去洗'+d+'件衣服'); }); -->打印去洗3件衣服 |
四.Promise错误处理 1. reject中存储错误处理的参数,可以传给then方法中的第二个参数
1 2 3 4 5 6 7 8 9 10 11 12 |
let p = new Promise((resolve,reject)=>{ setTimeout(()=>{ //resolve('读写成功'); reject('读写失败'); },2000) }); p.then((d)=>{ console.log('执行成功'); },(err)=>{ console.log(err); }); -->读写失败 |
五.Promise.all()-->一个脚本中有多个promise时,监控多个Promise对象执行完成 1.Promise.all([p1,p2,p3]):把promise打包,扔到一个数组里面,打包完还是一个promise对象.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
let p1 = new Promise((resolve,reject)=>{ let time = Math.random()*4000+1000; setTimeout(()=>{ console.log('p1完成'); resolve(); },time) }); let p2 = new Promise((resolve,reject)=>{ let time = Math.random()*4000+1000; setTimeout(()=>{ console.log('p2完成'); resolve(); },time) }); let p = Promise.all([p1,p2)]; p.then(()=>{ console.log(全部执行完毕); }) -->p1和p2全部执行完毕后,才会执行p.then方法里的操作 |
必须确保所有promise对象都是resolve状态 输出["aaaa","bbbb","cccc"] 六. 1.Promise对象的then方法有两个参数,一个是成功后的参数,另一个是失败的参数方法 promise.then(success,fail) 失败鸟 2.new Promise().catch()-->错误捕获 等同于上面的reject,返回“失败鸟” 也可这样使用 七.Promise的方法 1.Promise.resolve('xxx'):将现有的东西,转成一个Promise对象,且是resolve成功状态 输出aaa 等价于下面这句话 2.Promise.reject('xxx'):将现有的东西,转成一个Promise对象,且是reject失败状态 输出aaaa 4.Promise.race():与all的不同之处在于,只要有一个是resolve状态就可以返回 输出aaaa 八. 作者:祝名 链接:https://www.jianshu.com/p/7b1dd9c50d2b 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Details今天在一个原来使用AJAX自动缩小选择内容的项目上突然发现当输入名称时,如果输入有特殊字符&的时候,选择的内容不会发生变化,也就是说输入的内容在&后面的内容会被截断,经过查证才发现在客户端使用AJAX发送获取到客户端数据的时候,数据内容是没有经过url编码的就是直接放在url地址上发送了,因为当时考虑到输入的是公司名称,一般不会有特殊字符,也没认真考虑,使用当输入特殊字符&的时候后面的内容就会被截断。解决办法是对要发送的内容进行url编码,可以使用如下javascript函数: escape(),encodeURI(),以及encodeURIComponent()。这几种编码所起的作用各不相同。 escape() 方法: 采用ISO Latin字符集对指定的字符串进行编码。所有的空格符、标点符号、特殊字符以及其他非ASCII字符都将被转化成%xx格式的字符编码(xx等于该字符在字符集表里面的编码的16进制数字)。比如,空格符对应的编码是%20。 不会被此方法编码的字符: @ * / + encodeURI() 方法: 把URI字符串采用UTF-8编码格式转化成escape格式的字符串。 不会被此方法编码的字符:! @ # $& * ( ) = : / ; ? + ' encodeURIComponent() 方法: 把URI字符串采用UTF-8编码格式转化成escape格式的字符串。与encodeURI()相比,这个方法将对更多的字符进行编码,比如 / 等字符。所以如果字符串里面包含了URI的几个部分的话,不能用这个方法来进行编码,否则 / 字符被编码之后URL将显示错误。 不会被此方法编码的字符:! * ( ) ' 因此,对于中文字符串来说,如果不希望把字符串编码格式转化成UTF-8格式的(比如原页面和目标页面的charset是一致的时候),只需要使用 escape。如果你的页面是GB2312或者其他的编码,而接受参数的页面是UTF-8编码的,就要采用encodeURI或者 encodeURIComponent。 另外,encodeURI/encodeURIComponent是在javascript1.5之后引进的,escape则在javascript1.0版本就有。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/nich262/archive/2008/11/03/3208573.aspx from:https://www.cnblogs.com/seasons1987/p/3357775.html
View Details方式1:splice函数 arrayObject.splice(index,howmany,element1,…..,elementX) index:必选,规定从何处添加/删除元素。 howmany:必选,规定应该删除多少元素。未规定此参数,则删除从 index 开始到原数组结尾的所有元素。 element1:可选,规定要添加到数组的新元素。
1 2 3 4 |
<script type ="text/javascript"> var arr = [1,2,3,4]; arr.splice(0,arr.length); </script> |
方式2:给数组的length赋值为0
1 2 3 4 |
<script type ="text/javascript"> var arr = [1,2,3,4]; arr.length = 0; </script> |
赋予数组的长度小于本身的长度,数组中后面的元素将被截断。 赋予数组的长度大于本身的长度,将扩展数组长度,多的元素为undefined。 方式3:直接赋予新数组 []
1 2 3 4 |
<script type ="text/javascript"> var arr = [1,2,3,4]; arr = []; </script> |
这种方式为将arr重新复制为空数组,之前的数组如果没有被引用,将等待垃圾回收。 效率比较: 效率测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<script> var a = []; var b = []; var c = []; for(var i =0 ; i < 100000000;i++){ a.push(i); } console.time('splice'); a.splice(0,a.length); console.timeEnd('splice'); for(var i =0 ; i < 100000000;i++){ b.push(i); } console.time('length'); b.length = 0; console.timeEnd('length'); for(var i =0 ; i < 100000000;i++){ c.push(i); } console.time('赋值[]'); c = []; console.timeEnd('赋值[]'); </script> |
测试结果: splice: 0.010986328125ms length: 0.009033203125ms 赋值[]: 0.024169921875ms 多次测试发现第二种方式最快,第一种其次,大数据量下 第三种最慢。 测试结果可能不严谨。大家仅做参考。 from:https://www.cnblogs.com/jichi/p/10516576.html
View Details先重点说一下可能遇到的坑:主要在原本默认参数的设置以及两个方法的选择上,看完这篇总结你就知道怎么回事了~ throttle API走起 _.throttle(func, [wait=0], [options={}]) func (Function): 要节流的函数。 [wait=0] (number): 需要节流的毫秒数。 [options={}] (Object): 选项对象。 [options.leading=true] (boolean): 指定调用在节流开始前,默认true。 [options.trailing=true] (boolean): 指定调用在节流结束后,默认true。 throttle Demo走起(Vue写法)
1 2 3 4 5 6 |
testThrottle: _.throttle(function() { console.log("throttle"); }, 5000, { leading: true, trailing: false }) |
testThrottle方法被绑定在一个按钮上,demo最终的效果是 : 1、按钮点击后控制台立马打印了throttle——19:39:00; 2、5秒内点击多次按钮,最终只打印一次throttle——19:39:05前; 3、5秒后再点击一次,会重新打印throttle——19:39:05后; PS:lodash默认trailing为true,那么最终的效果是在点击时会立即打印throttle,且5秒后又会再打印一次,即节流之前和之后都会执行该节流函数。 throttle 总结走起 预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新的时间周期。 简言之:结束时间点不会随点击改变 debounce API走起 _.debounce(func, [wait=0], [options={}]) func (Function): 要防抖动的函数。 [wait=0] (number): 需要延迟的毫秒数。 [options={}] (Object): 选项对象。 [options.leading=false] (boolean): 指定在延迟开始前调用,默认false。 [options.maxWait] (number): 设置 func 允许被延迟的最大值。 [options.trailing=true] (boolean): 指定在延迟结束后调用,默认true。 debounce Demo走起
1 2 3 4 5 6 |
testDebounce: _.debounce(function() { console.log("debounce"); }, 2000, { leading: true, trailing: false }) |
testDebounce方法被绑定在一个按钮上,demo最终的效果是 : 1、按钮点击后控制台立马打印了debounce——19:39:00; 2、5秒内点击多次按钮,最终只打印一次debounce——19:39:05前,假设19:39:04完成了最后一次点击; 3、相对于最后一次点击的5秒后再点击一次,会重新打印debounce——19:39:09后; PS:lodash默认leading为false、trailing为true,那么最终的效果是在点击后等待5秒才会打印debounce,即延迟之前不执行函数,而是在延迟之后执行。 debounce 总结走起 当调用动作触发一段时间后,才会执行该动作,若在这段时间间隔内又调用此动作则将重新计算时间间隔。 简言之:结束时间点会随点击改变 综上所述,适用情况如下: throttle (1)对于键盘事件,当用户键入非常频繁,但我们又必须要在一定时间(阀值)内执行处理函数的时候。例如:一些网页游戏的键盘事件。 (2)对于鼠标移动和窗口滚动,鼠标的移动和窗口的滚动会带来大量的事件,但是在一段时间内又必须看到页面的效果。例如:对于可以拖动的div,如果使用debounce,那么div会在拖动停止后突然跳到目标位置;这时就需要使用throttle。 debounce (1)对于键盘事件,当用户输入比较频繁的时候,可以通过debounce合并键盘事件处理。例如:需要在用户输入完成时进行字符串校验。 (2)对于ajax请求的情况。例如:当页面下拉超过一定范围就通过ajax请求新的页面内容,这时候可以通过debounce合并ajax请求事件。 from:https://www.cnblogs.com/dreamsqin/p/11305028.html
View Details一、安装
1 |
cnpm i lodash -S |
二、方法一 1、引入
1 2 |
import _ from 'lodash' Vue.prototype._ = _ |
2、使用
1 |
this._.debounce(this.handleClick,1000,false) |
二、方法二 1、引入
1 |
let _ = require('lodash') |
2、使用
1 |
_.debounce(this.handleClick,1000,false) |
三、vue单文件组件中使用 里面分别有我自己写的debounce函数和lodash的debounce函数,效果一样!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<template> <div> <el-button @click="myDebounce">我的debounce</el-button> <el-button @click="_debounce">lodash的debounce</el-button> </div> </template> <script> import { debounce } from '@/utils/util' let _ = require('lodash') export default { methods: { handleClick1() { console.log(`真正执行的函数,次数比较少:handleClick1.....`) }, handleClick2() { console.log(`真正执行的函数,次数比较少:handleClick2.....`) }, myDebounce() { console.log(`myDebounce.....`) this.DB() }, _debounce() { console.log(`_debounce.....`) this._DB() } }, created() { this.DB = debounce(this.handleClick1, 1000, false) this._DB = this._.debounce(this.handleClick2,1000,false) } } </script> |
debounce测试.png 注意:以前我是在data选项里面定义DB:null,然后再methods里面初始化函数,但是需要判断‘如果有了就不赋函数,如果为空就赋’,发现比较麻烦;后来直接在created钩子里面定义,就很方便了! 作者:斐鸽传书 链接:https://www.jianshu.com/p/907e8a0ee5d7 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Details笔者最近因为公司需求开发使用vue和jquery开发抓娃娃H5极简小游戏,使用到setTimeout函数。遇到了1个坑
1 2 3 |
在vue的某个方法(点击后执行) setTimeout(this.end(),4000);//娃娃消失 |
这里奇怪的是,end方法的确被执行了。但是没有执行4s后执行的效果。那我要你合用呢!其实,问题还是出在笔者身上,大家请看下图 setTimeout的定义和用法。问题出在我的格式上面 其实是支持两种调用方式:1 字符 2 函数体(文章解决方式) 解决方法如下: 1、定义一个_this暂存this 2、再改变变量的值,则生效啦 3、方法中将this存在变量_this中,此时执行setTimeout函数时,setTimeout函数内的_this就会访问到这个变量,就会得到当前对象。
1 |
1 |
注意⚠️: 当在vue中使用定时器在function里直接使用this,发现没有效果,这是由于setTimeout函数调用的代码运行在与所在函数完全分离的执行环境上,这会使得this指向的是window对象。拓展知识:解决vue在setTimeout内修改this失效的问题 要想setTimeout指向正确的值,可以使用如下方法: 1、使用箭头函数
1 2 3 4 5 6 7 8 9 |
export default { methods: { start: function () { setTimeout(() => { this.end()//娃娃消失 }, 4000); } } } |
此时函数的this指向的是定义它的时候的对象,也就是this指向了data内中对应的变量。 码字不易,对大家有用最佳 from:https://blog.csdn.net/qq_27295403/article/details/83375574
View Details概述 我正在开发的项目前端和后端是完全独立的,通过配置 webpack 的 proxy 将前端请求跨域代理到后台服务。昨天发现,我前端执行 post 请求,后台 springmvc 的 @RequestMapping 接收不到对应的请求参数。开始我以为是我 proxy 配置有问题,导致 post 参数不能传到后台。然而,并不是这样… proxy 配置如下: 前端代码: java 后台代码: Request Payload VS Form Data 前端请求 我看了前端发起的请求,请求正文并不是我熟悉的 Form Data,而是 Request Payload。如图注意下面两个请求的 Content-Type 的区别。 Request Payload 请求 Form Data 请求 了解这两个的区别之前,我们先回顾下 HTTP 请求报文格式: Request Payload 大概格式如下,请求头部的 Content-Type: application/json,并且请求正文是一个 json 格式的字符串 Form Data 大概格式如下,请求头部的 Content-Type: application/x-www-form-urlencoded,并且请求正文是类似 get 请求 url 的请求参数 后台处理 对于 Request Payload 请求, 必须加 @RequestBody 才能将请求正文解析到对应的 bean 中,且只能通过 request.getReader() 来获取请求正文内容 对于 Form Data 请求,无需任何注解,springmvc 会自动使用 MessageConverter 将请求参数解析到对应的 bean,且通过 request.getParameter(…) 能获取请求参数 解决方案 综上,我在前端选择使用 Form Data 的方式来发起请求,使用 qs 库将 json 对象转化为字符串 (如 {name:’dahuang',age: 11} 转化为 name=dahuang&age=11)。 之前我以为 axios 会自动根据你的请求正文格式来选择发起 Form Data 还是 Request Payload 请求,但是执行 delete 操作时,如图的 Content-Type 却是 text/plain […]
View Details一般使用axios进行数据请求就是要使用异步请求,因为项目需求,需要同步请求,所以async+await了解一下: async用于声明一个函数是异步的,await用于声明在一个异步函数中等待语句执行完毕。也就是说await只能在async函数中使用 基本用法就是这样的:
1 2 3 4 5 |
methods: { async funA(){ var res = await axios.post('') //这里的res就是axios请求回来的结果 } } |
我这边是用在项目里的 common.js
1 2 3 |
async addImg(file, config) { return await axios.post(path.addImage, file, config); } |
vue页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
methods:{ async upload() { var self = this; var formData; for (let i = 0; i < this.imgList.length; i++) { const img = this.imgList[i]; formData = new FormData(); formData.append("file", img); formData.append("type", "goods_grade"); console.log(formData.getAll("file")); await this.$api.common .addImg(formData, { headers: { "Content-Type": "multipart/form-data" } }) .then(res => { if (res.data.code == 200) { this.$message({ type: "success", message: "添加成功" }); this.uploadSuccess = true; this.childrenImgs.push(res.data.result); this.$emit("change", this.childrenImgs); } else { this.$message({ type: "warning", message: res.data.message }); } }); } } } |
注意事项 如果同步请求是封装在其他函数中,那么每一个函数都需要做成异步函数。如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
methods: { fun1: async function () { await axios.get('url) }, fun2: async function () { ... await this.fun1() ... }, fun3: async function () { ... await this.fun2() ... }, } |
from:https://blog.csdn.net/liuy_1314/article/details/98483792
View Details1 获取?后面的参数 http://192.168.1.105:8080/#/idInput?username=%22%E5%BC%A0%E4%B8%89%22 获取参数方法 let id = this.$route.query.username 2 获取不带?的URL中的参数 http://192.168.1.12:8080/#/home/newsinfo/234 在路由中配置路由 { path: '/home/newsinfo/:id', component: Newsinfo } .vue页面设置 <template> <router-link :to="'/home/newsinfo/' + item.id"> </template> 获取参数方法 let id = this.$route.params.id ———————————————— 版权声明:本文为CSDN博主「woaizhuzhuxia521521」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/woaizhuzhuxia521521/article/details/83619520
View Details
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
var ws = new WebSocket("ws://localhost:8080/msg"); //readyState属性返回实例对象的当前状态,共有四种。 //CONNECTING:值为0,表示正在连接。 //OPEN:值为1,表示连接成功,可以通信了。 //CLOSING:值为2,表示连接正在关闭。 //CLOSED:值为3,表示连接已经关闭,或者打开连接失败 //例如:if (ws.readyState == WebSocket.CONNECTING) { } //【用于指定连接成功后的回调函数】 ws.onopen = function (evt) { console.log("Connection open ..."); ws.send("Hello WebSockets!"); }; //ws.addEventListener('open', function (event) { // ws.send('Hello Server!'); //}; //【用于指定收到服务器数据后的回调函数】 //【服务器数据有可能是文本,也有可能是二进制数据,需要判断】 ws.onmessage = function (event) { if (typeof event.data === String) { console.log("Received data string"); } if (event.data instanceof ArrayBuffer) { var buffer = event.data; console.log("Received arraybuffer"); } console.log("Received Message: " + evt.data); ws.close(); }; //[【于指定连接关闭后的回调函数。】 ws.onclose = function (evt) { console.log("Connection closed."); }; //发送文本 ws.send("Hello WebSockets!"); //发送Blob数据 var file = document .querySelector('input[type="file"]') .files[0]; ws.send(file); //发送ArrayBuffer var img = canvas_context.getImageData(0, 0, 400, 320); var binary = new Uint8Array(img.data.length); for (var i = 0; i < img.data.length; i++) { binary[i] = img.data[i]; } ws.send(binary.buffer); //webSocket.bufferedAmount //bufferedAmount属性,表示还有多少字节的二进制数据没有发送出去。它可以用来判断发送是否结束 var data = new ArrayBuffer(10000000); socket.send(data); if (socket.bufferedAmount === 0) { // 发送完毕 } else { // 发送还没结束 } //webSocket.onerror 用于指定报错时的回调函数 ws.onerror = function (event) { }; es.addEventListener("error", function (event) { }); |
from:https://www.cnblogs.com/liuqiyun/p/9984679.html
View Details