update: Ajax

This commit is contained in:
qianguyihao
2021-05-18 21:25:52 +08:00
parent acf4d69267
commit 1e775ba3e7
3 changed files with 26 additions and 26 deletions

View File

@@ -0,0 +1,165 @@
## 单线程
JavaScript 语言和执行环境是**单线程**即同一时间只能处理一个任务
具体来说所谓单线程是指 JS 引擎中负责解释和执行 JavaScript 代码的线程只有一个也就是一次只能完成一项任务这个任务执行完后才能执行下一个所有的任务都**需要排队**
**JS 为何要被设计为单线程呢**原因如下
- 首先是历史原因在最初设计 JS 这门语言时多进程多线程的架构并不流行硬件支持并不好
- 其次是因为多线程的复杂性多线程操作需要加锁编码的复杂性会增高
- 而且如果多个线程同时操作同一个 DOM在多线程不加锁的情况下会产生冲突最终会导致 DOM 渲染的结果不符预期
所以为了避免这些复杂问题的出现JS 被设计成了单线程语言
## 同步任务和异步任务
如果当前正在执行的任务很耗时它就会**阻塞**其他正在排队的任务为了解决这个问题JS 在设计之初将任务分成了两类同步任务异步任务
- 同步任务**主线程**上排队执行的任务只有前一个任务执行完毕才能执行下一个任务
- 异步任务不进入主线程而是进入**任务队列**Event Queue的任务只有"任务队列"通知主线程某个异步任务可以执行了该任务才会进入主线程执行
```js
console.log('同步任务');
setTimeout(() => {
console.log('异步任务');
}, 1000);
```
比如上面的代码里第一行代码是同步任务**立即执行**定时器里的回调函数是异步任务需要等 1 秒后才会执行
### 前端使用异步的场景
什么时候需要**等待**就什么时候用异步
- 定时任务setTimeout定时炸弹setInterval循环执行
- 事件绑定比如说按钮绑定点击事件之后用户爱点不点我们不可能卡在按钮那里什么都不做所以应该用异步
- 网络请求含接口请求ajax 请求网络图片加载
- ES6 中的 Promise
现在的大部分软件项目都是前后端分离的后端生成接口前端请求接口前端发送 ajax 请求向后端请求数据然后**等待一段时间**才能拿到数据这个请求过程就是异步任务
### 接口调用的方式
js 中常见的接口调用方式有以下几种
- 原生 ajax基于 jQuery ajax
- Promise
- Fetch
- axios
下一篇文章我们重点讲一下接口调用里的 Ajax然后在ES6语法中学习 **Promise**在这之前我们需要先了解同步任务异步任务的事件循环机制
### 多次异步调用的顺序
- 多次异步调用的结果顺序可能不同步
- 异步调用的结果如果**存在依赖**则需要通过回调函数进行嵌套
### 事件循环机制重要
![](http://img.smyhvae.com/20210517_1431.png)
执行顺序如下
- 同步任务进入主线程后立即执行
- 异步任务会先进入 Event Table等时间到了之后再进入 Event Queue然后排队为什么要排队因为同一时间JS 只能执行一个任务比如说`setTimeout(()=> {}, 1000)`这种定时器任务需要等一秒之后再进入 Event Queue
- 当主线程的任务执行完毕之后此时主线程处于空闲状态于是会去读取 Event Queue 中的任务队列如果有任务则进入到主线程去执行
## 代码示例
掌握了上面的事件循环原理之后我们来看几个例子
### 举例 1
```js
console.log(1);
setTimeout(() => {
console.log(2);
}, 1000);
console.log(3);
console.log(4);
```
打印结果
```
1
3
4
2
```
解释先等同步任务执行完成后再执行异步任务
### 举例 2重要
如果我把上面的等待时间 1 秒改成 0 你看看打印结果会是什么
```js
console.log(1);
setTimeout(() => {
console.log(2);
}, 0);
console.log(3);
console.log(4);
```
打印结果
```
1
3
4
2
```
可以看到打印结果没有任何变化这个题目在面试中经常出现考的就是 `setTimeout(()=> {}, 0)`会在什么时候执行这就需要我们了解同步任务异步任务的执行顺序即前面讲到的**事件循环机制**
解释先等同步任务执行完成后再执行异步任务
同理我们再来看看下面这段伪代码
```js
setTimeout(() => {
console.log('异步任务');
}, 2000);
// 伪代码
sleep(5000); //表示很耗时的同步任务
```
上面的代码中异步任务不是2秒之后执行而是等耗时的同步任务执行完毕之后才执行那这个异步任务是在5秒后执行还是在7秒后执行这个作业留给读者你来思考~
### 举例 3较真系列
```js
setTimeout(() => {
console.log('异步任务');
}, 1000);
```
上面的代码中等到 1 秒之后真的会执行异步任务吗其实不是
在浏览器中 setTimeout()/ setInterval() 的每调用一次定时器的最小时间间隔是**4ms**这通常是由于函数嵌套导致嵌套层级达到一定深度或者是由于已经执行的setInterval的回调函数阻塞导致的
上面的案例中异步任务需要等待1004毫秒之后才会从 Event Table 进入到 Event Queue这在面试中也经常被问到
## 参考链接
- [JS-同步任务异步任务微任务和宏任务](https://github.com/PleaseStartYourPerformance/javaScript/issues/34)
- [JS 同步异步宏任务微任务](https://juejin.cn/post/6875605533127081992)、[JavaScript 中事件循环的理解](https://zhuanlan.zhihu.com/p/364475433)、[javascript 事件循环机制](https://github.com/reng99/blogs/issues/34)
- [如何实现比 setTimeout 80 倍的定时器](https://mp.weixin.qq.com/s/NqzWkeOhqAU85XPkJu_wCA)

View File

@@ -1,6 +1,6 @@
## 同步和异步
## 同步和异步回顾
### 同步和异步的简单理解
@@ -23,9 +23,9 @@
试想一下如果没有异步刷新的话每次点击加载更多网页都要重新刷新体验就太糟糕了
web前端里的异步更新就要用到 Ajax
web前端里的异步更新就要用到 Ajax很多人说如果没有 Ajax就没有互联网的今天
关于同步和异步的更详细介绍可以参考本项目的另外一篇文章JavaScript基础ES6语法/单线程和异步
关于同步和异步的更详细介绍可以参考本项目的另外一篇文章05-JavaScript基础异步编程和Ajax/01-单线程和异步
@@ -33,12 +33,11 @@ web前端里的异步更新就要用到 Ajax。
### Ajax 的概念
在浏览器中我们可以在不刷新页面的情况下通过ajax的方式去获取一些新的内容
在浏览器中我们可以在不刷新页面的情况下通过 Ajax 的方式去获取一些新的内容
AjaxAsynchronous Javascript And XML异步 JavaScript XML它并不是凭空出现的新技术而是对于现有技术的结合Ajax 的核心是 js 对象**XMLHttpRequest**
### 发送 Ajax 请求的五个步骤
### Ajax原理发送 Ajax 请求的五个步骤
> 其实也就是 使用 XMLHttpRequest 对象的五个步骤
@@ -54,11 +53,11 @@ AjaxAsynchronous Javascript And XML异步 JavaScript 和 XML。它并
1创建异步对象 XMLHttpRequest 对象
2使用open方法设置请求参数`open(method, url, async)`参数解释请求的方法请求的url是否异步
2使用open方法设置请求参数`open(method, url, async)`参数解释请求的方法请求的url是否异步
3发送请求
3发送请求`send()`
4注册事件 注册onreadystatechange事件状态改变时就会调用
4注册事件注册onreadystatechange事件状态改变时就会调用
如果要在数据完整请求回来的时候才调用我们需要手动写一些判断的逻辑
@@ -84,29 +83,29 @@ AjaxAsynchronous Javascript And XML异步 JavaScript 和 XML。它并
document.querySelector('#btnAjax').onclick = function () {
// 发送ajax 请求 需要 五步
// 1创建异步对象
var ajaxObj = new XMLHttpRequest();
// 1创建XMLHttpRequest对象
var xmlhttp = new XMLHttpRequest();
// 2设置请求的参数。包括请求的方法、请求的url。
ajaxObj.open('get', '02-ajax.php');
xmlhttp.open('get', '02-ajax.php');
// 3发送请求
ajaxObj.send();
xmlhttp.send();
//4注册事件。 onreadystatechange事件状态改变时就会调用。
//如果要在数据完整请求回来的时候才调用,我们需要手动写一些判断的逻辑。
ajaxObj.onreadystatechange = function () {
xmlhttp.onreadystatechange = function () {
// 为了保证 数据 完整返回,我们一般会判断 两个值
if (ajaxObj.readyState == 4 && ajaxObj.status == 200) {
// 如果能够进这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
// 5.在注册的事件中 获取 返回的 内容 并修改页面的显示
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// 如果能够进这个判断说明数据请求成功了
// 5在注册的事件中获取返回的内容,并显示在页面上
console.log('数据返回成功');
// 数据是保存在 异步对象的 属性中
console.log(ajaxObj.responseText);
console.log(xmlhttp.responseText);
// 修改页面的显示
document.querySelector('h1').innerHTML = ajaxObj.responseText;
// 显示在页面上
document.querySelector('h1').innerHTML = xmlhttp.responseText;
}
}
}