1. 程式人生 > 其它 >【JavaWeb】學習筆記——Ajax、Axios

【JavaWeb】學習筆記——Ajax、Axios

Ajax

Ajax 介紹


AJAX(Asynchronous JavaScript And XML):非同步的JavaScript 和 XML

AJAX 的作用:

  • 與伺服器進行資料交換:通過AJAX可以給伺服器傳送請求,並獲取伺服器響應的資料
  • 非同步互動:可以在不重新載入整個頁面的情況下,與伺服器互動資料並更新部分網頁的技術

同步和非同步

AJAX 的缺點

  • 沒有瀏覽歷史,不能回退
  • 存在跨域問題(同源)
  • SEO(爬蟲) 不友好,爬不到資料

AJAX 快速入門

GET 請求基本操作

//給button按鈕繫結事件
const btn=document.getElementsByTagName('button')[0];
btn.onclick=function(){
    //1.建立核心物件
    const xhr=new XMLHttpRequest();
    const result=document.getElementById("result");
    //2.初始化 設定請求方法和 url
    xhr.open('GET','http://127.0.0.1:8000/ajaxservlet');
    //3.傳送
    xhr.send();
    //4.事件繫結 處理服務端返回的結果
    //on when  當...的時候
    //readystate 是 xhr 物件中的屬性表示狀態
    //               0:未初始化 1:open()方法呼叫完畢 2:send()方法呼叫完畢 
    //              3:服務端部分返回結果 4:服務端返回了所以結果
    //change 改變
    xhr.onreadystatechange =function(){
    //判斷(服務端返回了所有結果)
          if(xhr.readyState===4){
          //判斷響應狀態碼 200 404 403 401 500
          //2xx 表示成功
          if(xhr.status >= 200 && xhr.status < 305){
          //處理結果  行、頭、空行(在應用層沒有實際意義)、體
          //1.響應行
          // console.log(xhr.status);//狀態碼
          // console.log(xhr.statusText);//狀態字串
          // console.log(xhr.getAllResponseHeaders());//所有頭
          // console.log(xhr.response);//響應體
          //設定 result 的文字
           result.innerHTML=xhr.response;}

           else{

		   }
                }
            }
        }

PSOT 請求基本操作

//獲取元素物件
    const result =document.getElementById("result");
    //繫結事件
    result.addEventListener("mouseover",function(){
        //1.建立物件
        const xhr = new XMLHttpRequest();
        //2.初始化 設定型別與 URL
        xhr.open('POST','http://127.0.0.1:8000/server');
        //3.傳送
        xhr.send();
        //4.事件繫結
        xhr.onreadystatechange=function(){
        //判斷
        if(xhr.readyState===4){
           if(xhr.status>=200&&xhr.status<305)
             {
                //處理服務端返回的結果
                result.innerHTML = xhr.response;
              }
           }
        }
    });
服務端
@WebServlet("/ajaxservlet")
public class ServletDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1.響應資料
        resp.getWriter().write("hallo ajax");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }
}

案例


使用AJAX驗證使用者名稱是否存在
需求:在完成使用者註冊時,當用戶輸入框失去焦點時,校驗使用者名稱是否在資料庫已存在

前端程式碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form id="reg-form" action="#" method="get">
        <table>
            <tr>
                <td>使用者名稱</td>
                <td>
                    <input name="username" type="text" id="username">
                    <br>
                    <span id="username_err" style="display: none">使用者名稱已存在</span>
                </td>
            </tr>

            <tr>
                <td>密碼</td>
                <td>
                    <input name="password" type="password" id="password">
                    <br>
                </td>
            </tr>
        </table>
    </form>
</body>
<script>
    //1. 給使用者名稱輸入框繫結 失去焦點事件
    document.getElementById("username").onblur=function (){
        //2. 傳送ajax請求
        //獲取使用者名稱
        var username=this.value;

        //建立核心物件
        const xhr=new XMLHttpRequest();
        const result=document.getElementById("result");
        //初始化 設定請求方法和 url
        xhr.open('GET','http://localhost:8080/untitled_war/servletUserServlet?username='+username);
        xhr.send();//傳送
        //事件繫結 處理服務端返回的結果
        xhr.onreadystatechange =function(){
            if(xhr.readyState===4&&xhr.status >= 200 && xhr.status < 305) {//響應成功
               //判斷使用者名稱是否存在
               if(this.responseText=="true"){
                    //存在:顯示提示資訊
                   document.getElementById("username_err").style.display = '';
               }else {
                    //不存在:清楚提示資訊
                   document.getElementById("username_err").style.display = 'none';
               }
            }else {//響應失敗

            }
        }
    }
</script>
</html>
後端程式碼
package com.itheima.web;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/servletUserServlet")
public class AjaxServletDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 接收使用者名稱
        String username = req.getParameter("username");

        //2. 呼叫servlet 查詢User物件
        boolean flag = true;

        //3. 響應標記
        resp.getWriter().write(""+flag);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }
}

AJAX 相關操作


設定請求頭

//設定請求頭
//Content-Type:請求體型別
//application/x-www-from-urllencoded:引數查詢字串型別(固定型別)
xhr.setRequestHeader('Content-Type','application/x-www-from-urllencoded');
xhr.setRequestHeader('name','atguigu');

設定請求引數

//GET請求的引數在位址列中,這種方法容易暴露資料,非常不安全。
xhr.open('GET','http://127.0.0.1:8000/server?a=100&b=200&c=300');

//POST請求的引數在響應體重,相較於GET資料隱祕性更高。
xhr.send('a=100&b=200&c=300');
xhr.send('a:100&b:200&c:300');/*兩種方式都是有效的*/

JSON物件傳輸方法

  • 客戶端
//客戶端我們接收的還是一個字串,如果將這個字串裝為物件呢?
//方法一:手動對資料轉化
let data = JSON.parse(xhr.response);

//方法二:設定響應體資料的型別
xhr.responseType = 'json';
//注意:要在請求初始化的時候就定義
  • 服務端
//設定響應頭 設定允許跨域
response.setHeader('Access-Control-Allow-Origin','*');
//設定響應頭
response.setHeader('Access-Control-Allow-Headers','*');
//響應一個數據
const data={
    name:'孫悟空'
};
//進行字串轉換
let str=JSON.stringify(data);
//設定響應體
response.send(str);

請求超時與網路異常處理

  • 客戶端
//超時設定 超過2s
xhr.timeout=2000;
xhr.ontimeout=function(){//超時回撥
alert("網路異常,請稍後重試");
}

xhr.onerror=function(){//網咯異常回調
alert("你的網路好像有點問題");
}
  • 服務端
app.get('/delay',(request,response)=>{
    //設定響應頭 設定允許跨域
    response.setHeader('Access-Control-Allow-Origin','*'); 
    setTimeout(() => {
        //設定響應體
    response.send('延時響應');
    }, 3000);
});

取消請求

const xhr=new XMLHttpRequest();/*建立物件*/
xhr.abort();

同源策略


  • 是瀏覽器的一種安全策略。
  • 同源: 協議、域名、埠號 必須完全相同。 違背同源策略就是跨域

不過AJAX是預設滿足同源策略的

跨域解決方案一(只支援 get 請求。

在網頁中有一些標籤天生具有跨域能力,比如:img link iframe script。於是我們可以利用一個非官方的跨域解決方案JSONP 來解決跨域問題,它純粹憑藉程式設計師的聰明才智開發出來的,JSONP 就是利用script 標籤的跨域能力來發送請求的。

JSONP 使用
//1.動態的建立一個 script 標籤
var script = document.createElement("script");
//2.設定 script 的 src,設定回撥函式
script.src = "http://localhost:3000/testAJAX?callback=abc";
function abc(data)
{
  alert(data.name);
};
//3.將 script 新增到 body 中
document.body.appendChild(script);

// 4.伺服器中路由的處理
router.get("/testAJAX",function(req , res){
  console.log("收到請求");
  var callback = req.query.callback;
  var obj =  {name:"孫悟空", age:18 }
  res.send(callback+"("+JSON.stringify(obj)+")");
});

跨域問題解決方案二(支援 get 和 post 請求。

通過設定一個響應頭來告訴瀏覽器,該請求允許跨域,瀏覽器收到該響應以後就會對響應放行。
於是官方給我們提供了一個跨域解決方案 CORS(Cross-Origin Resource Sharing:跨域資源共享)。它的特點是不需要在客戶端做任何特殊的操作,完全在伺服器中進行處理,跨域資源共享標準新增了一組 HTTP 首部欄位,允許伺服器宣告哪些 源站通過瀏覽器有許可權訪問哪些資源

官方文件https://developer.mozilla.org/zh-CN/docs/web/http/cors

CORS 使用
 router.get("/testAJAX" , function (req , res) {
   //通過 res 來設定響應頭,來允許跨域請求
   //res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
   res.set("Access-Control-Allow-Origin","*");
   res.send("testAJAX 返回的響應");
 	})

Axios

Axios 非同步框架


Axios 是一個基於 promise 網路請求庫,作用於node.js 和瀏覽器中。 它是 isomorphic 的(即同一套程式碼可以執行在瀏覽器和node.js中)。在服務端它使用原生 node.js http 模組, 而在客戶端 (瀏覽端) 則使用 XMLHttpRequests。Axios 對原生的Ajax進行封裝,簡化書寫

官方網站:https://www.axios-http.cn/docs/intro

特性

  • 從瀏覽器建立 XMLHttpRequests
  • 從 node.js 建立 http 請求
  • 支援 Promise API
  • 攔截請求和響應
  • 轉換請求和響應資料
  • 取消請求
  • 自動轉換JSON資料
  • 客戶端支援防禦XSRF

安裝

用 npm:
$ npm install axios

使用 bower:
$ bower install axios

使用 yarn:
$ yarn add axios

使用 jsDelivr CDN:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

使用 unpkg CDN:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
快速入門——使用axios 傳送請求,並獲取響應結果
//GET
axios({
  method:"get",
  url:"http://localhost:8080/ajax-demo/aJAXDemo1?username=zhangshang"
}).then(function(resp)){
  alert(resp.data);
}

//POST
axios({
  method:"post",
  url:"http://localhost:8080/ajax-demo/aJAXDemo1"
  data:"username=zhangshang"
}).then(function(resp)){
  alert(resp.data);
}

Axios 請求別名

為了方便起見,Axios 已經為所有支援的請求方法提供了別名。

非常方便,閱讀性不強。根據開發場景自行選擇

  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

注意:在使用別名方法時, url、method、data 這些屬性都不必在配置中指定。

示例
//GET請求
axios.get("url")
    .then(function(resp)){
	alert(resp.data);
});

//POST請求
axios.post("url","引數")
    .then(function(resp)){
	alert(resp.data);
});