同步与异步
/* 同步异步是什么: 同步和异步是一种消息通知机制 同步阻塞: A调用B,B处理获得结果,才返回A A在这个过程中,一直等待B结果,没有拿到结果之前,需要A(调用者)一直等待和确认调用结果是否返回,拿到结果,然后继续再执行下去. 做一件事,没有拿到结果之前,就一直等待,一直等到有结果了,再去做下面的事. 异步非阻塞: A调用B,无需等待B结果,B通过状态,通知A或回调函数来处理. 做一件事,不用等待事情的结果,然后就去忙别的了,有了结果,再通过状态来告诉B,或者通过回调函数来处理. 生活例子 小明去图书馆借书,和管理员说找那本书,管理员就去一本本查,查完之后才告诉小明,有没有这个书; 小明A 图书馆管理员B 查的这个过程需要时间,所以 同步 -> 在管理员找到或者找不到的过程中,不回去通知小明,需要小明'一直'去问他结果 异步 -> 在管理员找到之后,就会'通知方式'去告诉小明,所以小明可以继续干别的事,等待通知管理员通知就行; */ { // 同步:阻塞 function test(){ console.log("test..."); } test(); console.log("end..."); // 代码执行过程: test... -> end... 因为他们是一步一步向下执行的; } { // 异步:非阻塞 // 在JS中非常典型的 异步函数 :定时器 function test(){ setTimeout(()=>{ console.log("test...") },1000) } test(); console.log("end..."); // 执行顺序 -> end... test... } { // 如何让test执行然后再执行end呢? // 1.直接把end放到 test中 // 2.回调 callback; function test(cd){ setTimeout(()=>{ console.log("test..."); cd && cd(); },1000); } test(function(){ console.log("end..."); }); // 执行顺序 -> test... end... }
异步小案例:方块运动
递归
{ function move(ele, direction, target) {//元素,方向(left,top),目标点 let start = parseInt(window.getComputedStyle(ele, null)[direction]);//(元素,伪类)[样式名]; -> 获取元素当前位置[有单位]; let speed = 5;//速度; start = start + speed; ele.style[direction] = start + "px"; // 不听的加 -> 递归(调用自身) setTimeout(() => { if (start === target) { console.log("停") } else { move(ele, direction, target); } }, 50); } move(box, 'left', 200) }
动画帧 requestAnimationFrame
{ // 动画帧,相对于 setTimeout 性能好一点; function move(ele, direction, target) { function fn() { let start = parseInt(window.getComputedStyle(ele, null)[direction]); let speed = 5; start = start + speed; ele.style[direction] = start + "px"; if (start == target) { console.log("停"); } else { window.requestAnimationFrame(fn); } } fn(); } move(box, 'left', 200) }
回调
{ // 如何从上面移动到下边呢 -> 回调 -> 也是回调地域 function move(ele, direction, target,cd) { function fn() { let start = parseInt(window.getComputedStyle(ele, null)[direction]); let dir = (target-start)/Math.abs(target-start);//判断 正负:(目标点-当前位置)除 Math.abs(目标点-当前位置) -> 1 / -1 // console.log( 10/Math.abs(10) );//1; // console.log( -10/Math.abs(-10) );//0-1; let speed = 5 * dir;//* 正得正 负得负 start = start + speed; ele.style[direction] = start + "px"; if (start == target) { console.log("停"); cd && cd(); } else { window.requestAnimationFrame(fn); } } fn(); } move(box,'left',200,function(){ move(box,'top',200,function(){ move(box,'left',0,function(){ move(box,'top',0); }) }) }); }
使用promise对象
{ // promise function move(ele, direction, target) { return new Promise(resolve => { function fn() { let start = parseInt(window.getComputedStyle(ele, null)[direction]); let dir = (target - start) / Math.abs(target - start); let speed = 5 * dir;//* 正得正 负得负 start = start + speed; ele.style[direction] = start + "px"; if (start == target) { // console.log("停"); resolve("停"); } else { window.requestAnimationFrame(fn); } } fn(); }); } move(box,'left',200).then(res=>{ return move(box,'top',200); }).then(res=>{ return move(box,'left',0); }).then(res=>{ return move(box,'top',0); }).then(res=>{ console.log(res); }) }
使用async和await
{ // async和await function move(ele, direction, target) { return new Promise(resolve => { function fn() { let start = parseInt(window.getComputedStyle(ele, null)[direction]); let dir = (target - start) / Math.abs(target - start); let speed = 5 * dir;//* 正得正 负得负 start = start + speed; ele.style[direction] = start + "px"; if (start == target) { // console.log("停"); resolve("停"); } else { window.requestAnimationFrame(fn); } } fn(); }); } async function queue() { try { await move(box, 'left', 200); await move(box, 'top', 200); await move(box, 'left', 0); await move(box, 'top', 0); console.log("全部执行完毕"); } catch (err) { // 接收错误; console.log(err); } } queue(); }
requestAnimationFrame 与 setTimerout性能比拼
{ function fn(){ document.title ++; setTimeout(()=>{ fn(); },1000); } // fn(); } { function fn(){ document.title ++; window.requestAnimationFrame(fn);//跳到别的浏览器就 停止了. } fn(); }
promise对象
{ /* Promise对象 是一个已经定义好的类; 三种状态:pending、resolve、reject */ let p1 = new Promise((resolve,reject)=>{ // 什么都不写 返回 -> pending value="undefined" // resolve(111);//resolve value="111" -> 在火狐中也叫:fulfilled 成功 // reject("error");//失败->报错 setTimeout(()=>{ resolve("成功了"); // reject("错误了"); },1000); }); // console.log(p1); // then -> 就是resolve成功 // then 两个参数; onresolve、onreject /* p1.then((res)=>{ console.log(res); },(error)=>{ console.log(error); }); */ /* p1.then((res)=>{ console.log(res); }).catch(err=>{//也是错误方法的一种方式 console.log(err); }) */ // then:三种返还; { // 1.回调里面没有返还 : 自动返还promise对象; /* let reslut = p1.then((res)=>{ console.log(res); }); console.log(reslut); */ // 2.回调有返还: 会自动通过promise包装返还值,然后返还promise对象; /* let reslut1 = p1.then((res)=>{ console.log(res); return "some value"; }); // 所以这里还可以继续 then; reslut1.then((res)=>{ console.log(res);//some value; }) console.log(reslut1); */ // 3.返还一个promise对象: then就会返还这个promise; let reslut2 = p1.then((res)=>{ return new Promise((resolve)=>{ resolve("返还的promise"); }); }); console.log(reslut2); } }
promise 加载图片小案例
{ function loadImg() { return new Promise((resolve, reject) => { let img = new Image(); img.src = "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=102864642,3880374403&fm=11&gp=0.jpg"; img.onload = function () { // console.log("加载完成"); resolve("图片加载完成"); document.querySelector("body").appendChild(img); } img.onerror = function(){ reject("图片加载失败"); } }); } loadImg().then(res=>{ console.log(res); },err=>{ console.log(err); }); }
async和await
// ES7语法: async 和 await; { let p1 = new Promise(resolve => { setTimeout(() => { resolve("执行成功") }, 1000) }) let p2 = new Promise(resolve => { setTimeout(function () { resolve("执行成功222") }, 2000) }); // 执行完p1然后执行p2 { // p1.then(res => { // console.log(res); // return p2; // }).then(res => { // console.log(res); // console.log("都执行完毕"); // }); } { // 异步函数用成了 同步写法 /* 1.async 和 await 要一起出现 2.await 一定要是一个promise对象; */ async function fn() { let res1 = await p1; console.log(res1); let res2 = await p2; console.log(res2); console.log("都执行完毕") } fn(); } }
Promise函数
{ // Promise是一个对象 resolve是它的静态方法 // let res = Promise.resolve(); // console.log(res);//能拿到 promise的resolve // let res1 = Promise.reject(); // console.log(res1);//reject状态的promise对象; let p1 = new Promise((resolve,reject)=>{ setTimeout(()=>{ console.log(111); resolve(111); },2000); }); let p2 = new Promise((resolve,reject)=>{ setTimeout(()=>{ console.log(222); resolve(222); // reject("error"); },1000); }); let p3 = new Promise((resolve,reject)=>{ setTimeout(()=>{ console.log(333); resolve(333); },3000); }); // 前提:所有的promise都要成功; // all 把成功结果放到数组中; // Promise.all([p1,p2,p3]).then(res=>{ // console.log(res); // }); // 拿到执行最快的那个 Promise.race([p1,p2,p3]).then(res=>{ console.log(res); }); }
来源:https://www.cnblogs.com/Afanadmin/p/12400293.html