您现在的位置是:首页 >技术杂谈 >前端异步编程全套:xmlhttprequest > ajax > promise > async/await网站首页技术杂谈
前端异步编程全套:xmlhttprequest > ajax > promise > async/await
异步编程
-
同步与异步区别
-
同步:按顺序,依次执行,向服务器发送请求-->客户端做其他操作
-
异步:分别执行,向服务器发送请求==>同时执行其他操作
-
原生xmlhttprequest
-
四步骤
-
创建ajax对象
-
var a=new xmlhttprequest();
-
-
设定数据的传输方式(get、post),打开连接open()
-
ajax对象.open("method","url","同步false/异步true")
-
-
获得响应数据
属性 描述 onreadystatechange 当readystate改变时就会调用该函数 responsetext 获得字符串形式的响应数据 responsexml 获得xml的形式的响应数据 readystate 0:请求未初始化 1:服务器连接已建立 2:请求处理中 3:请求处理中 4:请求已完成,且响应已就绪 status 200:ok 404:未找到页面 -
发送https请求:ajax.send()
-
-
数据交换格式【不能跨域】:
-
获取xml文件的内容,美观的渲染到页面
-
<button>获取数据</button> <table></table> <script> document.getElementsByTagName("button")[0].onclick=function(){ var ajax=new XMLHttpRequest; ajax.open("get","work1.xml",true); ajax.onreadystatechange=function(){ if(ajax.status==200&&ajax.readyState==4){ xixi(ajax.responseXML); } } ajax.send() } function xixi(obj){ var table="<table><tr><th>姓名</th><th>年龄</th><th>地址</th></tr>" var xml=obj.getElementsByTagName("xi"); for(i=0;i<xml.length;i++){ table+=`<tr><td>${xml[i].getElementsByTagName("name")[0].childNodes[0].nodeValue}</td> <td>${xml[i].getElementsByTagName("age")[0].childNodes[0].nodeValue}</td> <td>${xml[i].getElementsByTagName("address")[0].childNodes[0].nodeValue}</td></tr>` } document.getElementsByTagName("table")[0].innerHTML=table; } </script>
-
获取json文件的内容,美观的渲染到页面
-
<button>获取数据</button> <table></table> <script> document.getElementsByTagName("button")[0].onclick=function(){ //原生ajax,4个步骤 // 1.创建ajax对象 var ajax=new XMLHttpRequest; // 2.设置请求方式,地址,同步或异步 ajax.open("get","work.json",true); // 3.获得相应数据 // 如果请求状态改变触发函数 ajax.onreadystatechange=function(){ // 如果请求状态是4代表请求成功,并返回数据,并且正常访问服务器端页面 if(ajax.readyState==4&&ajax.status==200){ // 调用函数,传递实参,字符串格式的ajax对象数据 xixi(ajax.responseText); } } // 4.发送请求 ajax.send() } function xixi(obj){ var table="<table><tr><th>姓名</th><th>年龄</th><th>爱好</th></tr>" //反序列化==>把json格式转化成js对象格式 var xml=JSON.parse(obj); //是以数组里面写对象方式存储json数据的,所以循环数组,遍历每个对象 for(i in xml){ table+=`<tr><td>${xml[i].name}</td> <td>${xml[i].age}</td> <td>${xml[i].ah}</td></tr>` } //将拼接好的表格放在本页面上展示 document.getElementsByTagName("table")[0].innerHTML=table; } </script>
-
数据结构:
-
对象结构:{"key":"value","key":"value"}
-
数组结构:[value,value]
-
-
json语法注意事项:
-
属性名必须使用双引号包裹;
-
字符串类型的值必须使用双引号包裹;
-
JSON 中不允许使用单引号表示字符串;
-
JSON 中不能写注释;
-
JSON 的最外层必须是对象或数组格式,
-
不能使用 undefined 或函数作为 JSON 的值。
-
-
json与js对象的关系
-
JSON 是JS 对象的字符串表示法,它使用文本表示一个JS 对象的信息,本质是一个字符串。
-
js对象:var obj = {a: 'Hello', b: 'world'}
-
json:var json = '{"a": "Hello","b": "wor1d"}'
-
-
-
json和js相互转换
-
要实现从 JSON 字符串转换为 JS 对象,使用 JSON.parse() 方法:
var obj = json.parse('{"a": "he11o","b": "world"}'); //结果为{a:'He11o',b:'wor1d'}
-
要实现从JS 对象转换为 JSON 字符串,使用 JSON.stringify() 方法:
var obj = json.stringify({a: 'Hello'. b:'world'}): //结果为'{"a": "hello","b": "world"}
-
-
序列化与反序列化
-
把js-->json的过程,叫做序列化,json.stringify()函数就叫做序列化函数。
-
把json-->js的过程,叫做反序列化,json.parse()函数就叫做反序列化函数。
-
-
json比较xml的优点:方便,小,快
-
-
jquery的ajax
-
属性名称 值/描述 async 布尔值,表示是否异步,默认true type 请求类型(get/post) url 请求地址,默认当前页面 data 发送到服务器的数据 datatype 服务器响应的数据类型 beforesend(xhr) 发送请求前运行的函数 error(xhr,status,error) 请求失败运行的函数 success(result,status,xhr) 请求成功运行的函数 complete(xhr,status) 请求完成时运行的函数(请求成功和失败后都调用) -
方法 写法 ajax $.ajax({type,url,datatype,success}) post $.post(url,data,fn)或$.post(···) get $.get(url,fn)
promise
基础
-
ES6引入的异步编程新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果
-
Promise 构造函数:Promise(excutor){}
-
Promise.prototype.then 方法
-
Promise.prototype.catch 方法
-
-
常用在自定义封装函数
-
解释:在上面的代码中,我们使用async函数定义了一个异步函数foo,它内部使用await关键字等待fetch方法返回Promise对象的值。当fetch方法返回一个成功的结果后,它就会继续执行下面的代码,并使用await等待res.json()方法返回的Promise对象的值。如果没有发生错误,最终会将json对象打印到控制台上。如果发生了错误,可以使用try...catch语句来捕获异常并打印错误信息。
-
优点:
-
更加安全的代码:使用async/await方式,可以避免常见的错误,例如回调函数的作用域问题、回调函数顺序问题、回调地狱等
-
提高代码的运行效率,因为它可以避免回调函数带来的额外开销,并且可以更好地利用 JavaScript 引擎的特性,如单线程执行。
-
可以直接使用Promise对象的then()和catch()方法,便于代码的编写和维护。
-
实用:
-
// 第一种 var Promise = new Promise((resolve, reject) => { if (操作成功) { //成功后执行 resolve(value){} } else { //失败后执行 reject(error){} } }) // 第二种 Promise.then(function (value) { // 成功 }, function (value) { // 失败 })
-
//实例化Promise对象 const p = new Promise(function(resolve,reject){ setTimeout(() => { /* let data = 'data' resolve(data)//执行resolve表明调用成功 */ let data = 'error' reject(data)//执行reject表明调用失败,执行.then中的第二个回调函数 }, 1000); }) //调用promise对象的then方法 p.then(function(value){ console.log(value)//执行resolve后 },function(reson){ console.log(reson)//执行reject后 }) //Promise封装AJAX请求 //接口地址:https://api.apiopen.top/getJoke const p =new Promise((resolve,reject) => { //1.创建对象 const xhr = new XMLHttpRequest() //2.初始化 xhr.open("GET","https://api.apiopen.top/getJoke") //3.发送 xhr.send() //4.绑定事件 xhr.onreadystatechange = function(){ if(xhr.readyState === 4){ if(xhr.status>=200&&xhr.status<300){ //请求成功 resolve(xhr.response) }else{ //请求失败 reject(xhr.response) } } } }) //把请求结果提取出来,在外面进一步处理,不用在内部处理 p.then(function(value){ console.log(value) },function(reason){ console.error(reason) }) 复制代码 //创建promise对象 const p = new Promise((resolve,reject)=>{ setTimeout(() => { resolve('data') //reject('error') }, 1000); }) //then 方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定 //1.如果回调函数中返回的结果是 非Promise类型的属性(数值、字符串、不返回undefined等),状态为成功,返回值为对象的成功的值 //2.如果返回结果是promise对象,则该该promise对象的状态类型是什么返回的就是什么 //3.若抛出错误,则promise的返回rejected,且其值是抛出的值 const result = p.then(value => { //1.非promise类型的属性 return 123//执行则其状态为成功其result的成功值为123 //2.是promise对象 return new Promise((resolve,reject)=>{ resolve('OK') }) //3.抛出错误 throw new Error("出错") },reason => { console.warn(reason) }) //4.链式调用 嵌套异步任务 p.then(value=>{ },reason=>{ }).then(value=>{ },reason=>{ }) console.log(result) 复制代码 Promise实践 //引入fs模块 const { rejects } = require("assert") const fs = require("fs") const { resolve } = require("path/win32") /* fs.readFile('文件.md',(err,data1)=>{ fs.readFile("文件2.md",(err,data2)=>{ fs.readFile("文件3.md",(err,data3)=>{ let result = data1+' '+data2+' '+data3 console.log(result) }) }) }) *///传统方法实现易造成回调地狱 //使用Promise实现 const p = new Promise((resolve,reject)=>{ fs.readFile('文件.md',(err,data)=>{//第一个异步任务 resolve(data) }) }) p.then(value=>{//value第一个文件内容 //为避免回调地狱,再次搞一个promis对象,将其提出,再次.then return new Promise((resolve,reject)=>{//第二个异步任务 fs.readFile('文件2.md',(err,data)=>{//data第二个文件内容 resolve([value,data])//成功,返回也是成功 }) }) }).then(value=>{//一个包含文件和文件2内容的数组 return new Promise((resolve,reject)=>{//第三个异步 fs.readFile('文件3.md',(err,data)=>{//data第三个文件内容 value.push(data)//数组压入 resolve(value)//成功 返回也成功 }) }) }).then(value=>{//所有文件的数组 console.log(value.join(' ')) }) 复制代码 Pormise对象catch方法 const p = new Promise((value,reject)=>{ setTimeout(() => { reject("出错!") }, 1000); }) /* p.then(value=>{},reason=>{ console.error(reason) }) */ //then方法不指定第一个参数,即catch p.catch(reason=>{ console.warn(reason) })
async/await
基础
核心:async/await的核心思想是让异步代码像同步代码一样执行,把异步操作转换成同步操作。在这种方式下,不再需要使用回调函数,而是可以使用try...catch语句来处理异步操作的结果。
实用
-
实例:
async function foo() { try { const res = await fetch('https://api.example.com/user') const json = await res.json() console.log(json) } catch (error) { console.error(error) } } // async:标识 // await 等待后面执行完毕,转化成同步 // try{ } 函数体 // catch{ } 出现异常的函数