day17JS-Cookle、webStorage和Promise
1. 什么是Cookle
在网页中需要向当前电脑中存储一些数据,通过cookie可以存储。
Cookie :是一种由服务器发送到用户浏览器并保存在用户计算机上的小型文本文件,用于识别用户身份、跟踪用户活动、保存用户设置等。它通常包括名称、值、域名、路径、过期时间等字段。
其它相关的概念:
- 程序运行在电脑上或者手机上,都叫做客户端或者服务端。
- 客户端是用户显示使用的程序。
- 服务端是数据存储和操作的程序,为客户端提供数据的保障。
- 运行在插件或者其他程序中程序(runtime运行时)。
2. Cookle的使用方法
2.1 设置Cookle
document.cookie = "key=value";
注意!!!
如果key相同时就会覆盖上面key。
<script>
// 设置改变cookie
document.cookie = "key=value";
document.cookie = "name=xietian";
// 如果key相同时就会覆盖上面
document.cookie = "name=zhansang";
document.cookie = "age=20";
console.log(document.cookie);//key=value; name=zhansang; age=20
</script>
2.2 获取Cookle
<script>
// 设置改变cookie
document.cookie = "key=value"
document.cookie = "name=xietian"
// 如果key相同时就会覆盖上面
document.cookie = "name=zhansang"
document.cookie = "age=20"
// 获取cookie, //key=value; name=zhansang; age=20
function getCookie() {
//split(";") ---> key=value name=zhansang age=20
// 索引 0 1 2
return document.cookie.split(";").reduce((value, item) => {
//value是{},item是每一项的值
//{key=value,name=zhansang,age=20}
//split("=")---> [key,value] [name,zhansang] [age,20]
var arr1 = item.trim().split("=")
try {
value[arr1[0]] = JSON.parse(arr1[1]); //{key:value,name:zhansang,age:20}
} catch (e) {
value[arr1[0]] = arr1[1];
}
return value;
}, {})
}
var obj = getCookie();
console.log(obj);
</script>
2.3 删除Cookle
js不能直接删除Cookle
1. 直接关闭浏览器。window需要再进程杀掉谷歌。
2. 点击浏览器中清除所有会话按钮。
3. 浏览器 --->设置 ---> 隐私和安全。
4. 设置Cookle的存活时长。谷歌浏览器禁止超过1年以上的存储。
知识点补充:
date.toUTCString(); :所有UTC都是国际时间格林尼治时间,将时间转换为格林尼治时间字符串。
var date=new Date();
date.setFullYear( 2099 );
//所有UTC都是国际时间格林尼治时间将时间转换为格林尼治时间字符串//谷歌浏览器禁止超过1年以上的存储
document.cookie="name=xietian;expires="+date.toUTCString();
3. Cookie的类型
1. 会话Cookie(Session Cookies):这种类型的Cookie在浏览器关闭后就会被删除,主要用于保存用户的会话信息。由于它们不会在用户的计算机上长期保存,因此相对较为安全。
2. 持久Cookie(Persistent Cookies):与会话Cookie不同,持久Cookie会在用户的计算机上长期保存,直到其过期时间到达或被用户手动删除。这种类型的Cookie常用于保存用户的登录状态、个性化设置等信息。
3. 安全Cookie(Secure Cookies):安全Cookie只能通过HTTPS协议传输,不能通过未加密的HTTP协议传输。这增加了Cookie在传输过程中的安全性。
4. HttpOnly Cookie:HttpOnly是一个标志属性,用于防止JavaScript代码访问特定的Cookie。当设置了HttpOnly属性的Cookie被创建后,它将无法通过客户端脚本(如JavaScript)进行访问。这有助于减少跨站脚本攻击(XSS)的风险。
4. Cookle的特点
1、cookie的数据不能存储较大的数据(4-5K)。
2、cookie的数据会跟随访问服务端自动往返于客户端和服务端之间。
3、cookie必须在使用web服务的情况下才可以使用。
4、cookie存储是根据域名来存储,不同域名之间不能相互访问。
5、在前端发送请求到另一跨域地址中,也不会携带cookie。跨域是只要么ip地址不同,要么端口号不同。
6、cookie是有时效性,默认情况下,cookie是关闭浏览器就销毁;cookie在浏览器中如果禁止cookie,也不能存储cookie;浏览器可以随时销毁cookie,cookie可以通过设置保存时长来让cookie长期存储。
补充知识:
变量名.toUTCString(); :所有代UTC都是国际时间(格林尼治时间, 将时间转换为格林尼治时间字符串。
<script>
var date = new Date();
date.setFullYear(2099);
document.cookie = "name=xietian;expires=" + date.toUTCString();
</script>
7、cookie存储是按照路径存储的,每个路径下有自身的存储空间,相互之间方位。子级路径可以调用父级路径中cookie,但是父级路径无法调用子级路径中cookie,可以通过Path=设置路径让对应cookie存储在不同的级别上。
5. Cookle的作用
1. 会话管理:Cookie最初也是最主要的作用就是用于会话管理。当用户登录一个网站时,服务器会生成一个包含会话ID的Cookie并发送给浏览器,浏览器将这个Cookie保存在本地。此后,每次用户发送请求时,浏览器都会自动将这个Cookie发送给服务器,服务器通过会话ID识别用户身份,从而保持用户的登录状态。
2. 个性化设置:Cookie还可以用来保存用户的个性化设置,如主题、语言、字体大小等。这样,当用户再次访问网站时,网站可以根据Cookie中的信息为用户提供更加个性化的体验。
3. 购物车功能:在电子商务网站中,Cookie经常被用来实现购物车功能。当用户将商品添加到购物车时,这些信息会被保存在Cookie中。这样,即使用户关闭了浏览器或换了一台电脑,只要Cookie还在,购物车中的商品信息就不会丢失。
4. 跟踪用户行为:网站可以使用Cookie跟踪用户在网站上的行为,如访问了哪些页面、停留了多长时间、点击了哪些链接等。这些数据对于网站优化、广告投放等都非常有价值。
5. 第三方Cookie与广告定向:除了网站自己设置的Cookie外,还有一些第三方Cookie,它们通常由广告商或数据分析公司设置。这些Cookie可以用来跟踪用户在多个网站上的行为,从而为用户提供更加精准的广告定向服务。然而,这种跨站跟踪的行为也引发了关于隐私保护的争议。
6. Cookle可以做什么?
1、token(令牌):
情况1:网页登录时发送用户名和密码给服务端,服务端会把用户名和密码加密后,得到字符串通过setCookie的方式设置会访问的客户端浏览器,在对应客户端浏览器中存储cookie中token内容,当刷新页面,或者重新打开网站时,因为cookie自动携带发送给服务端特性,这时候token就会发送给服务端,服务端对token解密。md5除外,md5不能解码。
情况2 :或者将用户名和token发送给服务端,服务端去数据查询当前用户名的密码,然后根据指定的方式重新获取到token,然后比对发送来的toekn和服务端token是否一致来确定是否自动登录。
2、广告精准投放。
3、临时存储当前用户对应的数据。
7. webStorage
webStorage分两类:localStorage本地存储(长期存储)、sessionStorage会话存储。
localStorage可以看为一个对象,要存的key作为对象的属性,值就是这个结果。
7.1 设置localStorage
设置方法一:localStorage.属性名 = "属性值";
设置方法二:localStorage.setItem("属性名", "属性值");
<script>
localStorage.name = "xietian";
localStorage.age = 20;
localStorage.setItem("sex", "男")
</script>
7.2 获取localStorage
获取方法一:localStorage.属性名;
获取方法二:localStorage.getItem("属性名");
<script>
localStorage.name = "xietian";
localStorage.age = 20;
localStorage.setItem("sex", "男")
// 获取
console.log(localStorage.age);
console.log(localStorage.getItem("name"));
console.log(localStorage.getItem("sex"));
</script>
7.3 删除localStorage
删除方法一:delete localStorage.属性名;
删除方法二:localStorage.removeItem("属性名");
<script>
delete localStorage.name;
localStorage.removeItem("name");
</script>
7.4 清空localStorage
localStorage.clear();
<script>
localStorage.clear();
console.log(localStorage.length);
</script>
8. Cookle和webStorage的区别
相同点:cookie和webStorage都只能存储字符串的内容,如果不是字符串需要先转换为字符串存储。
区别:
1、LocalStorage是长期存储,不会自动删除,可以通过浏览器删除,也可以手动删除, sessionStorage是会话级存储,如果关闭网页就是丢失,cookie也是会话级,当设置时效就会有时效性存储。
2、webStorage的存储比较大4-5M,cookie只有4-5K存储。
3、LocalStorage存储不区分路径,sessionStorage即是同路径同页面不同的窗口打开数据不共享,cookie根据不同路径存储。
4、webStorage不会跟随发送通信发送给服务器,cookie会自动在前后端往返。
5、LocalStorage是可以侦听storage事件,但只能针对window侦听。当跨页面设置storage时,另一个页面将会收到LocalStorage被改变的事件内容。
这个页面:
<script>
window.addEventListener("storage", storageHandler);
function storageHandler(e) {
console.log(e);
}
</script>
另一个页面:
<script>
localStorage.num = 100;
</script>
6、LocalStorage可以用于大量数据的存储,比如部分js和css可以存储,用的时候可以直接调用,不需要下载对应js和css。
<script>
var script = document.createElement("script");
script.innerHTML = localStorage.lodash;
document.body.appendChild(script);
console.log(_.chunk([1, 2, 3, 4, 5, 6], 3));
</script>
9. 什么是Promise
Promise 是现代 JavaScript 中异步编程的基础。它是一个由异步函数返回的对象,可以指示操作当前所处的状态。在 Promise 返回给调用者的时候,操作往往还没有完成,但 Promise 对象提供了方法来处理操作最终的成功或失败。
使用方式:
<script>
var p = new Promise(function (resolve, reject) {
// resolve();
reject();
})
</script>
注意!!!
- 这个 resolve 和 reject 是两个回调函数名。
- 在Promise中执行了resolve就不会执行reject,执行reject就不会resolve。只执行其中一个回调函数。
resolve 和 reject 都可以传参,且仅能传一个参数。
10. Promise 实例对象的方法
- then() :最多接受两个参数(可以写两个函数),用于 Promise 兑现和拒绝情况的回调函数。它立即返回一个等效的 Promise 对象,允许你链接到其他 Promise 方法,从而实现链式调用。
- catch():用于在 Promise 链进行错误处理,因为它总是会返回一个 Promise,所以它可以和 then() 方法一样被链式调用。
当执行了Promise中resolve就会执行then中函数。
当执行了Promise中reject就会执行catch中函数。
p.then(function(){
}).catch(function(){
})
<sceipt>
// resolve和reject都可以传参,且仅能传一个参数
new Promise(function(resolve,reject){
resolve(1);
}).then(function(n){
console.log(n);
})
</sceipt>
案例1:
setTimeout(function(){
console.log("红灯");
},1000)
setTimeout(function(){
console.log("黄灯");
},2000)
setTimeout(function(){
console.log("绿灯");
},3000)
案例2:
setTimeout(fn1,1000);
function fn1(){
console.log("红灯");
setTimeout(fn2,2000);
}
function fn2(){
console.log("黄灯");
setTimeout(fn3,3000);
}
function fn3(){
console.log("绿灯");
}
案例3:
function showLight(light, time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log(light);
resolve();
}, time);
});
}
//链式调用
showLight("红灯",1000)
.then(function(){
// 在then 中return一个Promise
return showLight("黄灯",2000)
}).then(function(){
return showLight("绿灯",3000)
}).then(function(){
console.log("执行完成")
})
Promise写法格式:
写法一:
function fn(){
return new Promise(function(resolve,reject){
setTimeout(function(){
// resolve();
reject();
},1000)
})
}
fn().then(function(){
console.log("resolve");
}).catch(function(){
console.log("reject");
})
--------------------------------------------------------------
写法二:
function fn(){
return new Promise(function(resolve,reject){
setTimeout(function(){
// resolve();
reject();
},1000)
})
}
//then可以写两个函数
fn().then(function(){
// resolve执行
},function(){
// reject执行
})
10.1 resolve 和 reject的传参
// 传参
function fn(a){
return new Promise(function(resolve,reject){
setTimeout(function(){
if(a>0){
resolve("aaa");
}else{
reject("bbb")
}
},1000)
})
}
fn(-2).then(function(value){
console.log(value);
}).catch(function(reason){
console.log(reason);
})
10.2 then中关于return的问题
1. 如果在then中没有return一个Promise,则类似默认return一个Promise.resolve();。
function fn(a){
return new Promise(function(resolve,reject){
setTimeout(function(){
if(a>0){
resolve("aa")
}else{
reject();
}
},1000)
})
}
fn(1).then(function(value){
console.log(value);
// 如果在then中没有return一个Promise,则类似默认return一个Promise.resolve();
//类似默认如下:
// return new Promise(function(resolve){
// resolve();
// })
}).then(function(value){
console.log(value);
})
2.如果resolve执行时传参是Promise,相当于在执行了里面Promise后把里面resolve1的结果,传递外面resolve,然后再传递给then。
new Promise(function(resolve,reject){
// 如果resolve执行时传参是Promise,相当于在执行了里面Promise后把里面resolve1的结果,传递外面resolve,
// 然后再传递给then
resolve(new Promise(function(resolve1,reject1){
resolve1(1)
}))
}).then(function(value){
console.log(value);
})
案例:链式调用预加载问题
function loadImage(src){
return new Promise(function(resolve,reject){
var img=new Image();
img.src=src;
img.addEventListener("load",()=>{
resolve(img);
},{once:true})
})
}
var arr=[];
loadImage("./img/img_39.JPG")
.then(function(img){
arr.push(img);
return loadImage("./img/img_40.JPG")
}).then(function(img){
arr.push(img);
return loadImage("./img/img_41.JPG")
}).then(function(img){
arr.push(img);
return loadImage("./img/img_42.JPG")
}).then(function(img){
arr.push(img);
return loadImage("./img/img_43.JPG")
}).then(function(img){
arr.push(img);
console.log(arr);
})
10.3 Promise的状态机
状态机运行原理: 刚开始的时候状态是pending,当执行resolve时,判断状态是不是pending,如果当前状态不是pending,就不会执行resolve函数了。如果是pending就会执行resolve函数,并且重新修改当前的状态为fulfilled,再次执行resolve,当前状态已经是fulfilled,所以不会执行resolve了。如果执行reject,当前状态是pending状态,就会执行resolve,并且将状态修改为rejected,如果当前状态不是pending状态,就不会再次执行reject。
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled):意味着操作成功完成。当执行了resolve后就会触发状态改变为fulfilled。
- 已拒绝(rejected):意味着操作失败。当执行了reject后就会触发状态改变为rejected。
当我们在Promise中执行reject,但是没有设置then中第二个回调函数或者没有设置catch,就会报错。
报错案例:
var p=new Promise(function(resolve,reject){
resolve()
})
console.log(p);
1. 只能在then和catch中return的Promise才能被下一个then收到。
2. finally回调函数中return Promise不会向下面的then去传递。
案例:
function loadImage(src) {
return new Promise(function (resolve, reject) {
var img = new Image();
img.src = src;
img.onload=function(){
resolve(img)
}
img.onerror=function(){
reject(src);
}
});
}
var arr=[]
loadImage("./img/img_31.JPG")
.then(function(img){
arr.push(img);
}).catch(function(src){
}).finally(function(){
console.log("aaa");
// 只能在then和catch中return的Promise才能被下一个then收到
// finally回调函数中return Promise不会向下面的then去传递
return loadImage("./img/img_39.JPG")
}).then(function(img){
console.log("bbb");
arr.push(img);
console.log(arr);
})
11. Promise的静态方法
1. all() :同时异步多个Promise,并且返回resolve结果的列表。将所有需要Promise的对象放在数组中,然后把数组放在all里面,当then执行时,就会把每个Promise中resolve()传参的结果放在一个数组中传出。如果有一个出错,就会执行catch,不会执行then,必须保证所有Promise都会执行resolve。
案例1:
function loadImage(src) {
return new Promise(function (resolve, reject) {
var img = new Image();
img.src = src;
img.onload=function(){
resolve(img)
}
img.onerror=function(){
reject(src);
}
});
}
// all
// 同时异步多个Promise,并且返回resolve结果的列表
// 将所有需要Promise的对象放在数组中,然后把数组放在all里面,then执行时,就会把每个Promise中
// resolve()传参的结果放在一个数组中,传出
let arr=Array(5).fill(1).map((item,index)=>loadImage(`./img/img_${39+index}.JPG`));
Promise.all(arr).then(function(list){
console.log(list);
})
案例2:
function loadImage(src) {
return new Promise(function (resolve, reject) {
var img = new Image();
img.src = src;
img.onload=function(){
resolve(img)
}
img.onerror=function(){
reject(src);
}
});
}
let arr=Array(5).fill(1).map((item,index)=>loadImage(`./img/img_${38+index}.JPG`));
// 如果有一个出错,就会执行catch,不会执行then,必须保证所有Promise都会执行resolve
Promise.all(arr).then(function(list){
console.log(list);
}).catch(function(e){
console.log(e);
})
2. allSettled() :同时异步执行多个promise。在执行失败后仍然执行then,返回的内容中也是一个数组,数组中的内容是一个对象,对象中都有status值如果是"fulfilled"就是成功,如果是rejected就是失败的。如果成功,value就是返回的结果,如果失败,reason就是错误的结果。
案例:
function loadImage(src) {
return new Promise(function (resolve, reject) {
var img = new Image();
img.src = src;
img.onload=function(){
resolve(img)
}
img.onerror=function(){
reject(src);
}
});
}
let arr=Array(5).fill(1).map((item,index)=>loadImage(`./img/img_${38+index}.JPG`));
Promise.allSettled(arr).then(function(list){
// console.log(list);
list=list.reduce(function(value,item){
if(item.status==="fulfilled") value.push(item.value);
return value;
},[])
console.log(list);
})
3. race() :赛跑。同时对多个异步Promise执行,谁先执行完成resolve,就返回这个resolve的结果。如果有一个调用reject不会调用then。
function loadImage(src) {
return new Promise(function (resolve, reject) {
var img = new Image();
img.src = src;
img.onload=function(){
resolve(img)
}
img.onerror=function(){
reject(src);
}
});
}
let arr=Array(5).fill(1).map((item,index)=>loadImage(`./img/img_${38+index}.JPG`));
Promise.race(arr).then(function(img){
console.log(img);
})
4. any() :任意。同时对多个异步Promise执行,谁先执行完成resolve,就返回这个resolve的结果。 即是有reject,也会执行then。
function loadImage(src) {
return new Promise(function (resolve, reject) {
var img = new Image();
img.src = src;
img.onload=function(){
resolve(img)
}
img.onerror=function(){
reject(src);
}
});
}
let arr=Array(5).fill(1).map((item,index)=>loadImage(`./img/img_${38+index}.JPG`));
Promise.any(arr).then(function(img){
console.log(img);
})