大家好,我是不想干开发,什么都想试试的布布。今天,又是39摄氏度的一天,太热了(掘金社区麻烦安一下空调)。为了降降温,写点什么吧!想来想去,就我这点水平,只剩下异步可以浅浅的聊聊了。那咱就开始吧!
同步异步概念
单线程
-
js是单线程
-
单线程:同一时间只能做一件事情
-
为什么是单线程?
- 为了避免复杂性,例如同一时间操作相同DOM需考虑优先级一类的
-
同步和异步
-
同步和异步
-
同步和异步是一种消息通知机制
- 同步阻塞: A调用B,B处理获得结果,才返回给A。A在这个过程中,一直等待B的处理结果,没有拿到结果之前,需要A(调用者)一直等待和确认调用结果是否返回,拿到结果,然后继续往下执行。
做一件事,没有拿到结果之前,就一直在这等着,一直等到有结果了,再去做下边的事
console.log('你'); console.log('我'); console.log('他'); //执行结果为 你 我 他 按照代码执行顺序输出结果 console.log('你'); // callback 回调函数 function test(cb){//一般情况下,该函数是已经被封装好的函数,不允许直接修改,所以在创建时,可以预留一个回调函数用于实现同步 setTimeout(()=>{ console.log('他'); cb && cb(); },1000) } test(function(){ console.log('我'); }); //执行结果为 你 他 我- 异步非阻塞: A调用B,无需等待B的结果,B通过状态,通知等来通知A或回调函数来处理。
做一件事,不用等待事情的结果,然后就去忙别的了,有了结果,再通过状态来告诉我,或者通过回调函数来处理。
console.log('你'); // callback 回调函数 下一部分将会码文字解释 function test(){ setTimeout(()=>{ console.log('他'); },1000) } test(); console.log('我'); //执行结果为 你 我 他
-
异步处理方案
回调
-
回调
-
上面例子通过回调函数来处理异步,但是容易造成回调地狱
- 回调地狱:函数作为参数层层嵌套,前后关联性特别强(第一个回调出现异常不执行,后续回调将都不会执行且无法捕捉到异常)。回调地狱会导致代码可读性及可维护性变差。
-
function test(cb){
console.log('回调地狱');
cb && cb();
}
test(function(){
test(function(){
test(function(){
console.log("执行完成了");
})
})
})
运行结果:
自定义事件
方块运动实现
- 回调运动框架方块的运动
<!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>Document</title>
<style>
.box{
width: 100px;
height: 100px;
background: blue;
position:absolute;
left: 0px;
top: 0px;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
<script>
function move(el,direction,position,cb){
let start = parseInt(getComputedStyle(el,null)[direction]);
let speed = 5 * (position>start?1:-1);
setTimeout(()=>{
start+= speed;
if(start===position){
// console.log("运动完成");
cb && cb()
}else{
el.style[direction] = start + "px";
move(el,direction,position,cb);
}
},10)
}
let el = document.querySelector(".box");
move(el,'left',300,function(){
move(el,'top',300,function(){
move(el,'left',0,function(){
move(el,'top',0,function(){
console.log("运动完成");
})
})
})
});
</script>
</html>
没有结果动画,不想截。。。。。
promise使用
-
ES6 Promise 对象
-
两种参数:then的2个参数;onresolove 和 onreject;
-
ES6的Promise对象是一个构造函数,用来生成Promise实例。 所谓Promise对象,就是代表了未来某个将要发生的事件(通常是一个异步操作)。 它的好处在于,有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
-
Promise对象的三种状态 pending 、resolve 和 reject
let p1=new Promise(()=>{})
console.log(p1);
let p2 = new Promise((resolve,reject)=>{
resolve("success");
})
console.log(p2);
let p3 = new Promise((resolve,reject)=>{
reject("err");
})
console.log(p3);
可以看到返回值如下:
then方法
-
then 方法
-
then的返回值,会返回一个新的 Promise 对象,实现链式操作, 但是状态会有几种情况:
- then 的回调函数中没有返回值,then就会返回一个状态为: resolved 的 promise 对象
let p = new Promise((resolve,reject)=>{ resolve("success"); }) let p2=p.then(res=>{ }) console.log(p2); p2.then(res=>{ console.log(res) })
- then 的回调函数返回值是 非 promise 的值, then就会返回一个状态为: resolved 的 promise 对象,另外会把返回值,传递给 下一个 then
let p = new Promise((resolve,reject)=>{ resolve("success"); }) let p2=p.then(res=>{ return "成为优秀的人 请务必加油"; }) console.log(p2); p2.then(res=>{ console.log(res) })- then 的回调函数返回值是 promise 对象,then 就直接返回这个 promise 对象,具体的状态可以由我们自己定义,具体传递的值,也由我们自己定义
let p = new Promise((resolve,reject)=>{ resolve("success"); }) let p2 = p.then(res=>{ return new Promise((resolve,reject)=>{ resolve("今天的你也辛苦啦!"); }) }) p2.then(res=>{ console.log(res); }) console.log(p2);- Promise 下的方法:resolve、reject、all(收集成功后的结果返回一个数组,结果都必须是resolve的,不然收集不到结果。可以选择用allSettled)、race(谁执行的快,先抛出谁的结果)、finally(执行完成就会调用执行无论成功或失败)
-
async及await 改造promise
- Async 函数 和 await 改造promise;
- try及catch方法捕获错误
async function fn(){
}
console.log(fn());
结果:async函数也是基于promise构建的,generator分步执行
下一节将会手写promise,近一步了解其原理以及promise下的方法。