# 第七章 HTTP 请求实践

# XMLHttpRequest

XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容

属性
readyState 代表请求的状态码,0,1,2,3,4,
response 返回一个ArrayBuffer,Blob,Document,DOMString
responseText 返回响应 DOMString
responseType 一个用于定义响应类型的枚举值
responseURL 返回经过序列化的响应 URL
responseXML 返回一个 Document
status 响应状态码,比如:200
statusText 完整的响应状态文本,比如:200 OK
timeout 设置超时时间
upload XMLHttpRequestUpload 对象
withCredentials Boolean 指定请求是否携带授权信息
事件
onreadystatechange 变化
onload 成功完成
onerror 出错
onprogress 正在接收响应数据
onabort 中止
方法
open() 打开连接
send() 发送请求
abort() 中止请求
setRequestHeader() 设置请求头
getResponseHeader(0) 获取响应头

# XMLHttpRequest

<button>点击发送请求</button>
<div id="result"></div>
<script>
  // 获取元素
  const btn = document.getElementsByTagName("button")[0];
  const result = document.getElementById("result");
  btn.onclick = function () {
    console.log("click");
    const xhr = new XMLHttpRequest();
    document.cookie = "token=123456";
    xhr.withCredentials = true;
    xhr.open("GET", "http://127.0.0.1:8000/cors");
    xhr.send();
    // readystate 0 1 2 3 4  共有五种状态 0初始化 1已连接 2已发送 3已接收http头 4表示接受完整
    xhr.onreadystatechange = function () {
      // 判断服务端返回了所有结果
      if (xhr.readyState === 4) {
        // 判断响应状态码 200 404 403 401 500
        if (xhr.status >= 200 && xhr.status < 300) {
          // 1.响应行
          console.log(xhr.status); //状态码
          console.log(xhr.statusText); //响应的状态字符串
          console.log(xhr.getAllResponseHeaders); //响应头
          console.log(xhr.response); //响应体
          // 2.响应头
          result.innerHTML = xhr.response;
        }
      }
    };
  };
</script>

# setRequestHeader

<div id="result"></div>
<script>
  const result = document.getElementById("result");
  result.addEventListener("mouseenter", function () {
    console.log("mouseenter");
    const xhr = new XMLHttpRequest();
    xhr.open("POST", "http://127.0.0.1:8000/server");
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send("a=100&b=200&c=300");
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status >= 200 && xhr.status < 300) {
          result.innerHTML = xhr.response;
        }
      }
    };
  });
</script>

# JSON.parse()

<div id="result"></div>
<script>
  let method = "GET";
  let url = "http://127.0.0.1:8000/json-server";
  window.onkeydown = function () {
    const xhr = new XMLHttpRequest();
    xhr.open(methods, urk);
    xhr.send();
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if ((xhr.status >= 200) & (xhr.status < 300)) {
          console.log(xhr.response);
          result.innerHTML = JSON.parse(xhr.response).name;
        }
      }
    };
  };
</script>

# timeout

<button>点击发送请求</button>
<div id="result"></div>
<script>
  // 获取元素
  const btn = document.getElementsByTagName("button")[0];
  const result = document.getElementById("result");
  btn.addEventListener("click", function () {
    const xhr = new XMLHttpRequest();
    // 超时设置
    xhr.timeout = 2000;
    xhr.ontimeout = function () {
      alert("网络请求超时");
    };
    xhr.onerror = function () {
      alert("你的网络似乎出了一些问题");
    };
    xhr.open("GET", "http://127.0.0.1:8001/delay");
    xhr.send();
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if ((xhr.status >= 200) & (xhr.status < 300)) {
          result.innerHTML = xhr.response;
        }
      }
    };
  });
</script>

# abort

<button>发送请求</button>
<button>取消请求</button>
<script>
  const btns = document.querySelectorAll("button");
  let xhr = null;
  // 标志变量
  let isSending = false; //是否正在发送AJAX请求
  btns[0].onclick = function () {
    // 判断标志变量
    if (isSending) xhr.abort(); //如果正在发送,则取消之前的请求,产生新的请求
    xhr = new XMLHttpRequest();
    // 修改标志变量
    isSending = true;
    xhr.open("GET", "http://127.0.0.1:8000/delay");
    xhr.send();
    xhr.onreadystatechange = function () {
      if (x.readyState === 4) {
        // 修改标志变量
        isSending = false;
        if (x.status >= 200 && x.status < 300) {
        }
      }
    };
  };
  btns[1].onclick = function () {
    xhr.abort();
  };
</script>

# 实践

# server

npm install express
touch app.js
# 写服务端代码
code app.js
# 跑起来
nodemon app.js
const express = require("express");
const app = express();
app.get("/cors-server", (request, response) => {
  response.setHeader("Access-Control-Allow-Origin", "*");
  response.setHeader("Access-Control-Allow-Headers", "*");
  response.send("HELLO AJAX GET");
});

app.post("/cors-server", (request, response) => {
  response.setHeader("Access-Control-Allow-Origin", "*");
  response.setHeader("Access-Control-Allow-Headers", "*");
  response.send("<h1>HELLO AJAX POST</h1>");
});

app.all("/cors-server", (request, response) => {
  response.setHeader("Access-Control-Allow-Origin", "*");
  response.setHeader("Access-Control-Allow-Headers", "*");
  response.send("<h1>HELLO AJAX ALL</h1>");
});
app.all("/json-server", (request, response) => {
  response.setHeader("Access-Control-Allow-Origin", "*");
  response.setHeader("Access-Control-Allow-Headers", "*");
  const data = { name: "Gauss" };
  response.send(JSON.stringify(data));
});

// jsonp
app.all("/jsonp-server", (request, response) => {
  const data = {
    name: "gauss"
  };
  let str = JSON.stringify(data);
  response.end(`handle(${str})`);
});

app.listen(8000, () => {
  console.log(`服务已经启动,请访问http://localhost:${8000}`);
});

# ajax

// 接收一个对象
$.ajax({
  // 地址
  url: "http://127.0.0.1:8000/json-server",
  // 类型
  type: "GET",
  // 头信息
  headers: {
    c: 300,
    d: 400
  },
  // 参数
  data: { a: 100, b: 200 },
  // 响应体结果类型
  dataType: "text",
  // 超时时间
  timeout: 2000,
  // 成功回调
  success: function (data) {
    console.log(data);
  },
  // 失败回调
  error: function () {
    console.log("出错了");
  }
});

# axios

btns[0].onclick = function () {
  axios
    .get("/axios-server", {
      // url参数
      params: {
        id: 100,
        vip: 7
      },
      headers: {
        name: "gauss",
        age: 22
      }
    })
    .then((value) => {
      console.log(value);
    });
};

# fetch

fetch("http://127.0.0.1:8000/json-server", {
  method: "POST",
  headers: {
    name: "Gauss"
  },
  body: "username:admin&password=123456"
})
  .then((res) => {
    return res.json();
  })
  .then((res) => {
    // 这一步才真正出结果
    console.log(res);
  });

# jquery-jsonp

<button id="button">点击发送jsonp请求</button>
<div id="result"></div>
<script>
  function handle(str) {
    $("#result").html(JSON.stringify(str));
  }
  $("#button").click(function () {
    $.getJSON("http://127.0.0.1:8000/jsonp-server?callback=?", function (res) {});
  });
</script>

# script-jsonp

<input type="text" id="username" />
<p id="msg"></p>
<script>
  // 利用script的src属性,能让浏览器直接发起get请求,这样就不会触发跨域问题
  const input = document.querySelector("#username");
  const p = document.querySelector("#msg");
  function handle(data) {
    input.style.border = "solid 1px #f00";
    p.innerHTML = " data.msg " + data.msg + "\t\t\t\t" + "exist" + data.exist;
  }
  input.onblur = function () {
    let username = this.value;
    const script = document.createElement("script");
    script.src = "http://127.0.0.1:8000/jsonp-server";
    document.body.appendChild(script);
  };
</script>