您现在的位置是:首页 >技术杂谈 >前端异步编程全套:xmlhttprequest > ajax > promise > async/await网站首页技术杂谈

前端异步编程全套:xmlhttprequest > ajax > promise > async/await

前端嘻嘻哥 2023-06-16 08:00:02
简介前端异步编程全套:xmlhttprequest > ajax > promise > async/await

异步编程

  1. 同步与异步区别

    • 同步:按顺序,依次执行,向服务器发送请求-->客户端做其他操作

    • 异步:分别执行,向服务器发送请求==>同时执行其他操作

原生xmlhttprequest

  • 四步骤

    1. 创建ajax对象

      • var a=new xmlhttprequest();

    2. 设定数据的传输方式(get、post),打开连接open()

      • ajax对象.open("method","url","同步false/异步true")

    3. 获得响应数据

      属性描述
      onreadystatechange当readystate改变时就会调用该函数
      responsetext获得字符串形式的响应数据
      responsexml获得xml的形式的响应数据
      readystate0:请求未初始化 1:服务器连接已建立 2:请求处理中 3:请求处理中 4:请求已完成,且响应已就绪
      status200:ok 404:未找到页面
    4. 发送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>
      1. 数据结构:

        • 对象结构:{"key":"value","key":"value"}

        • 数组结构:[value,value]

      2. json语法注意事项:

        • 属性名必须使用双引号包裹;

        • 字符串类型的值必须使用双引号包裹;

        • JSON 中不允许使用单引号表示字符串;

        • JSON 中不能写注释;

        • JSON 的最外层必须是对象或数组格式,

        • 不能使用 undefined 或函数作为 JSON 的值。

      3. json与js对象的关系

        • JSON 是JS 对象的字符串表示法,它使用文本表示一个JS 对象的信息,本质是一个字符串。

          • js对象:var obj = {a: 'Hello', b: 'world'}

          • json:var json = '{"a": "Hello","b": "wor1d"}'

      4. 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"}
      5. 序列化与反序列化

        • 把js-->json的过程,叫做序列化,json.stringify()函数就叫做序列化函数。

        • 把json-->js的过程,叫做反序列化,json.parse()函数就叫做反序列化函数。

      6. json比较xml的优点:方便,小,快

jquery的ajax

  1. 属性名称值/描述
    async布尔值,表示是否异步,默认true
    type请求类型(get/post)
    url请求地址,默认当前页面
    data发送到服务器的数据
    datatype服务器响应的数据类型
    beforesend(xhr)发送请求前运行的函数
    error(xhr,status,error)请求失败运行的函数
    success(result,status,xhr)请求成功运行的函数
    complete(xhr,status)请求完成时运行的函数(请求成功和失败后都调用)
  2. 方法写法
    ajax$.ajax({type,url,datatype,success})
    post$.post(url,data,fn)或$.post(···)
    get$.get(url,fn)

promise

基础

  1. ES6引入的异步编程新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果

    1. Promise 构造函数:Promise(excutor){}

    2. Promise.prototype.then 方法

    3. Promise.prototype.catch 方法

  2. 常用在自定义封装函数

  3. 解释:在上面的代码中,我们使用async函数定义了一个异步函数foo,它内部使用await关键字等待fetch方法返回Promise对象的值。当fetch方法返回一个成功的结果后,它就会继续执行下面的代码,并使用await等待res.json()方法返回的Promise对象的值。如果没有发生错误,最终会将json对象打印到控制台上。如果发生了错误,可以使用try...catch语句来捕获异常并打印错误信息。

  4. 优点:

    1. 更加安全的代码:使用async/await方式,可以避免常见的错误,例如回调函数的作用域问题、回调函数顺序问题、回调地狱等

    2. 提高代码的运行效率,因为它可以避免回调函数带来的额外开销,并且可以更好地利用 JavaScript 引擎的特性,如单线程执行。

    3. 可以直接使用Promise对象的then()和catch()方法,便于代码的编写和维护。

实用:

  1.          

    // 第一种
        var Promise = new Promise((resolve, reject) => {
         if (操作成功) {
             //成功后执行
              resolve(value){}
           } else {
             //失败后执行
              reject(error){}
           }
        })
    // 第二种
        Promise.then(function (value) {
         // 成功
        }, function (value) {
         // 失败
        })
    ​
  2. 
    //实例化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语句来处理异步操作的结果。

实用

  1. 实例:

    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{ } 出现异常的函数

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。