同步与异步
/*
同步异步是什么: 同步和异步是一种消息通知机制
同步阻塞:
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);
});
}