update: ajax异步任务
This commit is contained in:
		
							parent
							
								
									07102a7261
								
							
						
					
					
						commit
						48a1ab234f
					
				| @ -22,31 +22,41 @@ JavaScript 语言和执行环境是**单线程**。即同一时间,只能处 | ||||
| 
 | ||||
| -   异步任务:不进入主线程、而是进入**任务队列**(Event Queue)的任务。只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。 | ||||
| 
 | ||||
| 代码举例: | ||||
| 
 | ||||
| ```js
 | ||||
| console.log('同步任务'); | ||||
| console.log('同步任务1'); | ||||
| 
 | ||||
| setTimeout(() => { | ||||
|     console.log('异步任务'); | ||||
| }, 1000); | ||||
| 
 | ||||
| console.log('同步任务2'); | ||||
| ``` | ||||
| 
 | ||||
| 比如上面的代码里:第一行代码是同步任务,会**立即执行**;定时器里的回调函数是异步任务,需要等 1 秒后才会执行。 | ||||
| 打印结果是: | ||||
| 
 | ||||
| 比如说,网络图片的请求,就是一个异步任务。前端如果同时请求多张网络网络图片,谁先请求完成就让谁先显示出来。 | ||||
| ``` | ||||
| 同步任务1 | ||||
| 同步任务2 | ||||
| 异步任务 | ||||
| ``` | ||||
| 
 | ||||
| 假如网络图片的请求做成同步任务,那就会出大问题,所有图片都得排队加载,如果第一张图片未加载完成,就得卡在那里,造成阻塞,导致其他图片都加载不出来。页面看上去也会很卡顿,这肯定是不能接受的。 | ||||
| 代码解释:第一行代码是同步任务,会**立即执行**;定时器里的回调函数是异步任务,需要等 1 秒后才会执行。假如定时器里的代码是同步任务,那需要等待1秒后,才能执行最后一行代码`console.log('同步任务2')`,也就是造成了主线程里的同步任务阻塞,这不是我们希望看到的。 | ||||
| 
 | ||||
| 比如说,网络图片的请求,就是一个异步任务。前端如果同时请求多张网络网络图片,谁先请求完成就让谁先显示出来。假如网络图片的请求做成同步任务,那就会出大问题,所有图片都得排队加载,如果第一张图片未加载完成,就得卡在那里,造成阻塞,导致其他图片都加载不出来。页面看上去也会很卡顿,这肯定是不能接受的。 | ||||
| 
 | ||||
| ### 前端使用异步的场景 | ||||
| 
 | ||||
| 什么时候需要**等待**,就什么时候用异步。 | ||||
| 什么时候需要**等待**,就什么时候用异步。常见的异步场景如下: | ||||
| 
 | ||||
| -   定时器:setTimeout(定时炸弹)、setInterval(循环执行) | ||||
| -   1、定时器:setTimeout(定时炸弹)、setInterval(循环执行) | ||||
| 
 | ||||
| -   事件绑定(比如说,按钮绑定点击事件之后,用户爱点不点。我们不可能卡在按钮那里,什么都不做。所以,应该用异步) | ||||
| -   2、事件绑定(比如说,按钮绑定点击事件之后,用户爱点不点。我们不可能卡在按钮那里,什么都不做。所以,应该用异步) | ||||
| 
 | ||||
| -   网络请求(含接口请求):ajax 请求、网络图片加载 | ||||
| -   3、网络请求(含接口请求):ajax 请求、网络图片加载 | ||||
| 
 | ||||
| -   ES6 中的 Promise | ||||
| -   4、ES6 中的 Promise | ||||
| 
 | ||||
| 现在的大部分软件项目,都是前后端分离的。后端生成接口,前端请求接口。前端发送 ajax 请求,向后端请求数据,然后**等待一段时间**后,才能拿到数据。这个请求过程就是异步任务。 | ||||
| 
 | ||||
| @ -61,11 +71,6 @@ js 中常见的接口调用方式,有以下几种: | ||||
| 
 | ||||
| 下一篇文章,我们重点讲一下接口调用里的 Ajax,然后在 ES6 语法中学习 **Promise**。在这之前,我们需要先了解同步任务、异步任务的事件循环机制。 | ||||
| 
 | ||||
| ### 多次异步调用的顺序 | ||||
| 
 | ||||
| -   多次异步调用的结果,顺序可能不同步。 | ||||
| 
 | ||||
| -   异步调用的结果如果**存在依赖**,则需要通过回调函数进行嵌套。 | ||||
| 
 | ||||
| ### 事件循环机制(重要) | ||||
| 
 | ||||
| @ -80,6 +85,13 @@ js 中常见的接口调用方式,有以下几种: | ||||
| -   当主线程的任务执行完毕之后,此时主线程处于空闲状态,于是会去读取 Event Queue 中的任务队列,如果有任务,则进入到主线程去执行。 | ||||
| 
 | ||||
| 
 | ||||
| ### 多次异步调用的顺序 | ||||
| 
 | ||||
| -   多次异步调用的结果,顺序可能不同步。 | ||||
| 
 | ||||
| -   异步调用的结果如果**存在依赖**,则需要通过回调函数进行嵌套。 | ||||
| 
 | ||||
| 
 | ||||
| ## 定时器:代码示例 | ||||
| 
 | ||||
| 掌握了上面的事件循环原理之后,我们来看几个例子。 | ||||
| @ -162,7 +174,8 @@ setTimeout(() => { | ||||
| 上面的案例中,异步任务需要等待 1004 毫秒之后,才会从 Event Table 进入到 Event Queue。这在面试中也经常被问到。 | ||||
| 
 | ||||
| ## 异步任务举例 | ||||
| ### 例1:加载图片 | ||||
| 
 | ||||
| ### 例 1:加载图片 | ||||
| 
 | ||||
| ```js
 | ||||
| // 加载图片的异步任务
 | ||||
| @ -193,8 +206,31 @@ loadImage( | ||||
| ); | ||||
| ``` | ||||
| 
 | ||||
| ### 例 2:定时器计时,移动 DOM 元素 | ||||
| 
 | ||||
| ### 例2:定时器计时 | ||||
| ```js
 | ||||
| // 函数封装:定义一个定时器,每间隔 delay 毫秒之后,执行 callback 函数
 | ||||
| function myInterval(callback, delay = 100) { | ||||
|     let timeId = setInterval(() => callback(timeId), delay); | ||||
| } | ||||
| 
 | ||||
| myInterval((timeId) => { | ||||
|     // 每间隔 500毫秒之后,向右移动 .box 元素
 | ||||
|     const myBox = document.getElementsByClassName('box')[0]; | ||||
|     const left = parseInt(window.getComputedStyle(myBox).left); | ||||
|     myBox.style.left = left + 20 + 'px'; | ||||
|     if (left > 300) { | ||||
|         clearInterval(timeId); | ||||
| 
 | ||||
|         // 每间隔 10 毫秒之后,将 .box 元素的宽度逐渐缩小,直到消失
 | ||||
|         myInterval((timeId2) => { | ||||
|             const width = parseInt(window.getComputedStyle(myBox).width); | ||||
|             myBox.style.width = width - 1 + 'px'; | ||||
|             if (width <= 0) clearInterval(timeId2); | ||||
|         }, 10); | ||||
|     } | ||||
| }, 200); | ||||
| ``` | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -58,6 +58,76 @@ Ajax:Asynchronous Javascript And XML(异步 JavaScript 和 XML)。它并 | ||||
| 
 | ||||
| (5)服务端响应,获取返回的数据。 | ||||
| 
 | ||||
| ## XMLHttpRequest 对象详解 | ||||
| 
 | ||||
| 我们在上一段讲解了使用 XMLHttpRequest 对象的五个步骤。本段,我们讲一下注意事项。 | ||||
| 
 | ||||
| ### 发送请求 | ||||
| 
 | ||||
| 发送请求的方法: | ||||
| 
 | ||||
| ```javascript
 | ||||
| open(method, url, async); | ||||
| ``` | ||||
| 
 | ||||
| 参数解释: | ||||
| 
 | ||||
| -   method:请求的类型;GET 或 POST | ||||
| 
 | ||||
| -   url:文件在服务器上的位置 | ||||
| 
 | ||||
| -   async:true(异步)或 false(同步) | ||||
| 
 | ||||
| 另外还有个方法:(仅用于 POST 请求) | ||||
| 
 | ||||
| ```javascript
 | ||||
| send(string); | ||||
| ``` | ||||
| 
 | ||||
| ### POST 请求时注意 | ||||
| 
 | ||||
| 如果想让 像 form 表单提交数据那样使用 POST 请求,就需要使用 XMLHttpRequest 对象的 setRequestHeader()方法 来添加 HTTP 头。然后在 send() 方法中添加想要发送的数据: | ||||
| 
 | ||||
| ```javascript
 | ||||
| xmlhttp.open('POST', 'ajax_test.php', true); | ||||
| 
 | ||||
| xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); | ||||
| 
 | ||||
| xmlhttp.send('name=smyhvae&age=27'); | ||||
| ``` | ||||
| 
 | ||||
| ### onreadystatechange 事件 | ||||
| 
 | ||||
| 注册 onreadystatechange 事件后,每当 readyState 属性改变时,就会调用 onreadystatechange 函数。 | ||||
| 
 | ||||
| readyState:(存有 XMLHttpRequest 的状态。从 0 到 4 发生变化) | ||||
| 
 | ||||
| -   0: 请求未初始化 | ||||
| 
 | ||||
| -   1: 服务器连接已建立 | ||||
| 
 | ||||
| -   2: 请求已接收 | ||||
| 
 | ||||
| -   3: 请求处理中 | ||||
| 
 | ||||
| -   4: 请求已完成,且响应已就绪 | ||||
| 
 | ||||
| status: | ||||
| 
 | ||||
| -   200: "OK"。 | ||||
| 
 | ||||
| -   404: 未找到页面。 | ||||
| 
 | ||||
| 在 onreadystatechange 事件中,**当 readyState 等于 4,且状态码为 200 时,表示响应已就绪**。 | ||||
| 
 | ||||
| ### 服务器响应的内容 | ||||
| 
 | ||||
| -   responseText:获得字符串形式的响应数据。 | ||||
| 
 | ||||
| -   responseXML:获得 XML 形式的响应数据。 | ||||
| 
 | ||||
| 如果响应的是普通字符串,就使用 responseText;如果响应的是 XML,使用 responseXML。 | ||||
| 
 | ||||
| ## 手写 Ajax | ||||
| 
 | ||||
| ### 手写第一个 Ajax 请求 | ||||
| @ -223,76 +293,30 @@ myAjax('a.json', (res) => { | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ### Ajax 多个接口的嵌套请求(重要) | ||||
| 
 | ||||
| ## XMLHttpRequest 对象详解 | ||||
| 我们在做异步任务的时候,经常会涉及到多个接口的嵌套请求。比如说,接口 1 请求完成后,需要根据接口 1 的数据请求接口 2;接口 2 请求完成后,需要根据接口 3 的数据请求接口 3,以此类推。 | ||||
| 
 | ||||
| 我们在上一段讲解了使用 XMLHttpRequest 对象的五个步骤。本段,我们讲一下注意事项。 | ||||
| 需求描述: | ||||
| 
 | ||||
| ### 发送请求 | ||||
| -   请求接口 1,根据用户名获取用户 id | ||||
| 
 | ||||
| 发送请求的方法: | ||||
| -   请求接口 2,根据用户 id 获取用户的年龄、性别等信息。 | ||||
| 
 | ||||
| ```javascript
 | ||||
| open(method, url, async); | ||||
| 代码实现思路: | ||||
| 
 | ||||
| ```js
 | ||||
| myAjax('http://localhost:8888/php/user.php?name=千古', (userInfo) => { | ||||
|     // 根据第一个接口返回的 userInfo.id,继续请求第二个接口
 | ||||
|     myAjax(`http://localhost:8888/php/houdunren.php?id=${userInfo['id']}`, (res) => { | ||||
|         console.log(response); | ||||
|     }); | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| 参数解释: | ||||
| 我们在实战开发中,经常会涉及到接口请求之间的**依赖**:需要上一个接口请求返回的数据,来发送本次请求。这种场景经常遇到,需要记住。 | ||||
| 
 | ||||
| -   method:请求的类型;GET 或 POST | ||||
| 
 | ||||
| -   url:文件在服务器上的位置 | ||||
| 
 | ||||
| -   async:true(异步)或 false(同步) | ||||
| 
 | ||||
| 另外还有个方法:(仅用于 POST 请求) | ||||
| 
 | ||||
| ```javascript
 | ||||
| send(string); | ||||
| ``` | ||||
| 
 | ||||
| ### POST 请求时注意 | ||||
| 
 | ||||
| 如果想让 像 form 表单提交数据那样使用 POST 请求,就需要使用 XMLHttpRequest 对象的 setRequestHeader()方法 来添加 HTTP 头。然后在 send() 方法中添加想要发送的数据: | ||||
| 
 | ||||
| ```javascript
 | ||||
| xmlhttp.open('POST', 'ajax_test.php', true); | ||||
| 
 | ||||
| xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); | ||||
| 
 | ||||
| xmlhttp.send('name=smyhvae&age=27'); | ||||
| ``` | ||||
| 
 | ||||
| ### onreadystatechange 事件 | ||||
| 
 | ||||
| 注册 onreadystatechange 事件后,每当 readyState 属性改变时,就会调用 onreadystatechange 函数。 | ||||
| 
 | ||||
| readyState:(存有 XMLHttpRequest 的状态。从 0 到 4 发生变化) | ||||
| 
 | ||||
| -   0: 请求未初始化 | ||||
| 
 | ||||
| -   1: 服务器连接已建立 | ||||
| 
 | ||||
| -   2: 请求已接收 | ||||
| 
 | ||||
| -   3: 请求处理中 | ||||
| 
 | ||||
| -   4: 请求已完成,且响应已就绪 | ||||
| 
 | ||||
| status: | ||||
| 
 | ||||
| -   200: "OK"。 | ||||
| 
 | ||||
| -   404: 未找到页面。 | ||||
| 
 | ||||
| 在 onreadystatechange 事件中,**当 readyState 等于 4,且状态码为 200 时,表示响应已就绪**。 | ||||
| 
 | ||||
| ### 服务器响应的内容 | ||||
| 
 | ||||
| -   responseText:获得字符串形式的响应数据。 | ||||
| 
 | ||||
| -   responseXML:获得 XML 形式的响应数据。 | ||||
| 
 | ||||
| 如果响应的是普通字符串,就使用 responseText;如果响应的是 XML,使用 responseXML。 | ||||
| 但这种层层嵌套的代码,会导致**回调地域**的问题,也不利于维护。我们在后续的 ES6 章节中,会讲解 Promise,它是一种更优雅的异步任务解决方案。 | ||||
| 
 | ||||
| ## jQuery 中的 Ajax | ||||
| 
 | ||||
| @ -302,14 +326,18 @@ JQuery 作为最受欢迎的 js 框架之一,常见的 Ajax 已经帮助我们 | ||||
| 
 | ||||
| ```javascript
 | ||||
| $.ajax({ | ||||
|     url: '01.php', //请求地址
 | ||||
|     data: 'name=fox&age=18', //发送的数据
 | ||||
|     url: 'https://xxx.com/getUserInfo.php', // 接口的请求地址
 | ||||
|     data: 'name=fox&age=18', // 请求参数
 | ||||
|     type: 'GET', //请求的方式
 | ||||
|     success: function (argument) {}, // 请求成功执行的方法
 | ||||
|     success: function (argument) { | ||||
|         // 接口请求成功时调用
 | ||||
|         console.log('接口请求成功'); | ||||
|     }, | ||||
|     beforeSend: function (argument) {}, // 在发送请求之前调用,可以做一些验证之类的处理
 | ||||
|     error: function (argument) { | ||||
|         console.log(argument); | ||||
|     }, //请求失败调用
 | ||||
|         // 接口请求失败时调用
 | ||||
|         console.log('接口请求失败'); | ||||
|     }, | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| @ -332,15 +360,17 @@ $.ajax({ | ||||
|             $(function () { | ||||
|                 $('#btn').click(function () { | ||||
|                     $.ajax({ | ||||
|                         url: 'data.php', | ||||
|                         url: 'https://xxx.com/getUserInfo.php', // 接口的请求地址
 | ||||
|                         dataType: 'text', | ||||
|                         data: 'name=fox&age=18', // 请求参数
 | ||||
|                         type: 'get', | ||||
|                         success: function (data) { | ||||
|                             console.log('接口请求成功'); | ||||
|                             alert(data); | ||||
|                             //$("#showInfo").html(data);
 | ||||
|                             // $("#showInfo").html(data);
 | ||||
|                         }, | ||||
|                         error: function (e) { | ||||
|                             console.log(e); | ||||
|                         error: function (err) { | ||||
|                             console.log('接口请求失败:' + err); | ||||
|                         }, | ||||
|                     }); | ||||
|                 }); | ||||
| @ -370,3 +400,7 @@ echo $text; | ||||
| 扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| ``` | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user