版权声明:刘家军 https://blog.csdn.net/qq_42911663/article/details/85692011
什么是js异步?
我们常常听到单线程、多线程、同步、异步这些概念,那么这些东西到底是什么呢?
1.单线程就是只有一个主线的线程,代码从上往下顺序运行,主线程负责执行程序的所有代码(UI展现以及刷新,网络请求,本地存储等等)废话不多说直接上代码感受下:
例如:一个项目从产品逻辑 => 设计原型图 => 前端+后台 => 测试 => 发布上线 ,这些流程都是由你自己来完成就是单线程
2.多线程顾名思义,就是有多个线程的程序,可以由用户自主创建。用户自主创建的若干进程相对于主线程而言就是子线程。子线程和主线程都是独立的运行单元,各自的执行互不影响,因此能够并发执行。
例如:一个项目分了多种流程 然后每个人只负责其中一部分,各自都有各自负责的一部分,一起合作完成这个项目就是多线程
3.同步的意思就像你在电话上要预约一个酒店,问前台有没有房间,然后没有挂掉电话,一直等,直到前台查询完有没有房间再回答你
4.异步就是你在电话上要预约一个酒店,问前台有没有房间,然后先挂掉电话,你可以做一些其他事情,然后等前台查询之后再给你回个电话告诉你
异步-定时器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript异步</title>
</head>
<body>
<script>
console.log("我是1")
setTimeout(() =》{
console.log("我是定时器")
},500)
console.log("我是2")
</script>
</body>
</html>
看下输出,没什么意外:
异步-ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript异步</title>
</head>
<body>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<script>
let allData = null;
function ajax() {
axios.get('https://easy-mock.com/mock/5c249dbe46e8386d0b21b475/example_copy_copy/test')
.then(data => {
console.log("ajax返回成功");
allData = data.data
console.log(allData );
}).catch(error => {
console.log("ajax返回失败");
})
}
ajax()
</script>
</body>
</html>
看下输出,仍在我们意料之中:
但是如果两个异步函数相遇了呢?上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript异步</title>
</head>
<body>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<script>
let allData = null;
function ajax() {
axios.get('https://easy-mock.com/mock/5c249dbe46e8386d0b21b475/example_copy_copy/test')
.then(data => {
console.log("ajax返回成功");
allData = data.data.data
console.log(allData );
}).catch(error => {
console.log("ajax返回失败");
})
}
console.log("我是1")
setTimeout(() =>{
console.log("我是定时器")
},500)
ajax()
console.log("我是2")
</script>
</body>
</html>
输出:
发现问题了吗?两个异步函数相遇了,先执行谁?谁跑的快就先执行谁?
也可以这么说,那么现在又引出一个知识点
任务队列和事件循环
console.log(“我是1”)与console.log(“我是2”);是同步执行的,他们都在js的主线程上执行,
在主线程之外还存在一个任务队列,任务队列中存放着需要异步执行的内容
当主线程运行完毕之后,就会去执行任务队列中的任务(不断的重复扫描)直到任务队列清空
继续看代码
setTimeout(function(){
console.log("我是定时器")
}, 0);
console.log("我是1");
输出:
为什么会这样?
console.log(“我是1”);在主线程中,先执行,
定时器是异步操作所以把定时器的内容,放在了任务队列中,
只有在主线程执行完了才会去执行任务列队中的内容
为什么主线程的任务执行完了后需要不断的扫描任务列队中的内容呢?
继续上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript异步</title>
</head>
<body>
<button class="btn">点击</button>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<script>
let btn = document.querySelector('.btn');
let allData = null;
function ajax() {
axios.get('https://easy-mock.com/mock/5c249dbe46e8386d0b21b475/example_copy_copy/test')
.then(data => {
console.log("ajax返回成功");
allData = data.data.data
console.log(allData );
}).catch(error => {
console.log("ajax返回失败");
})
}
console.log("我是1")
setTimeout(() =>{
console.log("我是定时器")
},500)
ajax()
console.log("我是2")
btn.onclick = () =>{
console.log("我点击了")
}
</script>
</body>
</html>
为button按钮绑定点击事件,在页面刷新的时候一直点击它 输出:
这样是不是可以理解为什么主线程要去循环扫描任务列队了?
事件循环的每一轮称为一个tick,类似vue中nextTick;扩展阅读:vue.nextTick
当产生用户交互(页面滚动事件,鼠标点击事件,窗口大小变化事件等等),ajax,定时器,计时器等,会向事件循环中的任务队列添加事件,然后等待执行
预知后事如何,且听下次分解