GET请求
GET 请求一般用于信息获取,它没有请求主体,而是使用 URL 传递参数(即:传递数据给后台)。
传递参数的方式:
- 对所需发送的数据(具有名称和值)执行普通的 URL 编码,即:由一对对 "名称=值" 组成(称为:名/值对),每一对之间用 "&" 拼接,如 "name=value&name=value&...&name=value";
- 由于 名/值对 会附加在 URL 地址后面,因此在这串字符参数的最前面需要添加个 "?",表示 URL 的 查询参数 开始。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tryrun 10</title>
</head>
<body>
<div id="form">
<label for="country">国家:<input type="text" name="country" id="country"></label>
<label for="city">城市:<input type="text" name="city" id="city"></label>
</div>
<hr>
<div>你查询的国家是:<span id="ipt_country"></span></div>
<div>你查询的城市是:<span id="ipt_city"></span></div>
<br>
<button type="button" id="search">查询</button>
(查询成功后会把你输入的值显示在上方)
<script>
var oSearch = document.getElementById("search"),
oIpt_country = document.getElementById("ipt_country"),
oIpt_city = document.getElementById("ipt_city");
var url = "/statics/demosource/demo_get_json.php";
oSearch.onclick = function () {
var country = document.getElementById("country").value,
city = document.getElementById("city").value;
var query = "country=" + country + "&city=" + city;
var queryURL = url + "?" + query;
// 发起 get 请求
ajaxGet(queryURL);
}
function ajaxGet (url) {
var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
var res = JSON.parse(xhr.responseText);
oIpt_country.innerText = res.params.country;
oIpt_city.innerText = res.params.city;
}
}
}
xhr.open("GET", url);
xhr.send();
}
</script>
</body>
缓存问题
对于 GET 请求,请求的结果会被浏览器缓存,特别是在 IE 浏览器下。这时,如果 GET 请求的 URL 不变,那么请求的结果就是浏览器的缓存(也就是上次 GET 请求的结果)。
解决办法
实时改变 GET 请求的 URL,只要 URL 不同,就不会取到浏览器的缓存结果。
在 URL 末尾添加时间戳参数。由于时间戳可以精确到毫秒,从而保证了每次发起 GET 请求的时间不同,达到实时改变请求 URL 的目的。
var url = "/statics/demosource/demo_get_json.php";
// 在请求参数的最后附加时间戳参数 t
var query = "user=" + user + "&pwd=" + pwd + "&t=" + new Date().getTime();
var queryURL = url + "?" + query;
// ajax_get为自己封装的请求对象,不是固定用法
ajax_get(queryURL);
封装 GET 异步请求函数
步骤:
-
实例化一个
XMLHttpRequest对象,如果你正在使用 IE7 以下版本的浏览器,应该对它做兼容处理; -
对
data数据执行普通的 URL 编码,也可以使用预置代码中提供的urlencodeData工具函数完成这步操作; -
调用
open()方法,指定请求方式、请求地址、是否异步,注意请求地址需要是url与请求参数拼接的结果; -
调用
send()方法; -
给
XMLHttpRequest实例添加readystatechange事件处理程序: -
- 最好在
open()方法调用之前实现readystatechange事件,比较严谨; - 在事件处理程序中判断 HTTP 请求状态,只有请求状态为 "完成" 时,才能保证响应内容完整;
- 最好在
-
根据 HTTP 状态码(即
status属性值),执行对应的回调函数: -
- HTTP 状态码在 200 与 300 之间(不包括300)、或为 304 都表示成功:使用
JSON.parse()方法将responseText属性值解析为 JavaScript 对象,并作为success函数的实参传出; - HTTP 状态码为其它值则表示请求失败:调用
error函数,并将失败的 HTTP 状态码作为实参传出;
- HTTP 状态码在 200 与 300 之间(不包括300)、或为 304 都表示成功:使用
-
在运行结果区封装的
ajaxPost,能否正常响应,常见的错误有:- 成功请求的测试出现 403:GET 请求的 URL 地址不正确,可以检查一下是否在
url与 请求参数之间拼接了 "?"。
- 成功请求的测试出现 403:GET 请求的 URL 地址不正确,可以检查一下是否在
<html>
<head>
<meta charset="UTF-8">
<script>
function ajaxGet (url, data, success, error) {
// 在下方开始你的代码
var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');
data = urlencodeData (data)
console.log(data);
xhr.onreadystatechange = function(){
if(xhr.readyState !== 4) return;
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(xhr.status);
var res = JSON.parse(xhr.responseText)
success(res);
}else{
var res = JSON.parse(xhr.responseText)
console.log(res);
error(res);
}
};
url = url + '?' + data;
xhr.open('GET',url,true);
xhr.send(null);
}
</script>
<!-- 工具函数 -->
<script>
// 用于对 JavaScript 对象执行普通的 URL 编码
// 编码后的格式为:"名称=值&...&名称=值"
function urlencodeData (data) {
if (!data) return;
var pairs = [];
for (var name in data) {
if (!data.hasOwnProperty(name)) continue;
if (typeof data[name] === "function") continue;
var value = (data[name] === null || data[name] === undefined) ? "" : data[name].toString();
pairs.push(encodeURIComponent(name) + "=" + encodeURIComponent(value));
}
return pairs.join("&");
}
</script>
<!-- 以下均是测试代码 -->
<!-- 测试代码的 css 部分 -->
<style>
#request { text-align: center; }
.request-result { padding: 12px; border: 1px solid #e8e8e8; border-radius: 2px; box-shadow: 0 1px 3px 1px #d9dfe9; }
.request-btn { margin-top: 12px; padding: 7px; color: #fff; border-radius: 7px; transition: all .2s; cursor: pointer; }
.request-success { background-color: #1890ff; }
.request-success:hover { background-color: #40a9ff; }
.request-error { background-color: #d9363e; }
.request-error:hover { background-color: #ff7875; }
</style>
</head>
<body>
<!-- 测试代码的 html 部分 -->
<div id="request">
<div class="request-result">
<div class="res-tip">测试下你封装的异步 GET 请求能不能正常响</div>
<div class="res-param"></div>
</div>
<div class="request-btn request-success">成功请求的测试</div>
<div class="request-btn request-error">失败请求的测试</div>
</div>
<!-- 测试代码的 js 部分 -->
<script>
var oDivs = document.getElementsByTagName("div");
var oResult_tip = oDivs[2],
oResult_param = oDivs[3],
oSuccess = oDivs[4],
oError = oDivs[5];
var url = "/statics/demosource/demo_get_json.php",
badUrl = "/statics/demosource/404.txt";
var data = {
aa:null,
from: "南昌",
to: "厦门",
time: "今天"
};
var success = function (res) {
oResult_tip.innerText = "请求成功";
oResult_param.innerHTML = "<div><span>起点:</span><span>" + res.params.from + "</span></div><div><span>终点:</span><span>" + res.params.to + "</span></div><div><span>时间:</span><span>" + res.params.time + "</span></div>";
};
var error = function (res) {
oResult_tip.innerText = "请求失败:" + res;
oResult_param.innerHTML = "";
};
oSuccess.onclick = function () {
ajaxGet(url, data, success, error);
};
oError.onclick = function () {
ajaxGet(badUrl, data, success, error);
}
</script>
</body>
</html>
POST请求
POST 请求一般用于修改服务器上的资源,它需要发送一个请求主体,客户端传递给服务器的数据就包含在这个请求主体中。
"Content-Type"请求头用于设置请求主体的编码格式。
表单编码的 POST 请求
POST 请求使用 表单编码 的方式来发送数据的关键步骤:
- 对所需发送的数据(具有名称和值)执行普通的 URL 编码,即:像 GET 请求那样拼接为 名/值 对的形式;
- 将
"Content-Type"请求头的值设置为"application/x-www-form-urlencoded"。
// 获取用户输入的表单数据
var country = document.getElementById("country").value,
city = document.getElementById("city").value;
// 将数据拼接为 名/值对 的形式
var query = "country=" + country + "&city=" + city;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
// ... ... 省略事件处理程序
}
// 指定 POST 请求
xhr.open("POST", "/statics/demosource/demo_post_json.php");
// 设置请求主体的编码方法
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 发送请求主体(数据)
xhr.send(query);
JSON 编码的 POST 请求
JSON 是一种轻量级的前后端数据交换格式,直接使用JSON.stringify原生 API 即可实现 JSON 编码,比表单编码的方式更加快捷。
POST 请求使用 JSON编码 的方式来发送数据的关键步骤:
"Content-Type"请求头的值需要为"application/json";- 对请求主体进行序列化,在 JavaScript 中可使用
JSON.stringify完成这步操作。
// 获取用户输入的表单数据
var country = document.getElementById("country").value,
city = document.getElementById("city").value;
// 将数据转换为 JavaScript 对象
var data = {
country : country,
city : city
}
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
// ... ... 省略事件处理程序
}
// 指定 POST 请求
xhr.open("PO ST", "/statics/demosource/demo_json_data.php");
// 设置请求主体的编码方法
xhr.setRequestHeader("Content-Type", "application/json");
// 编码请求主体并发送
xhr.send(JSON.stringify(data));
两种方式的比较
GET 请求:
- 一般用于信息
获取:通过发送一个请求来取得服务器上的资源; - 数据包含在 URL 地址中;
- 数据量受 URL 的长度限制;
- 不安全:浏览器的 URL
可见到,明文传输; - GET 请求
会被缓存; - GET 没有请求主体,请求速度相对较快。
POST 请求:
- 一般用于
修改服务器上的资源:向指定资源提交数据,后端处理请求后往往会导致服务器 建立新的资源 或 修改已有资源; - 数据包含在请求主体中;
- 没有数据量限制,可在服务器的配置里进行限制;
- 只能是比 GET
安全,实际上也是不安全的:可通过开发者工具或者抓包看到,明文传输; - POST 请求
不会缓存; - POST 相对稳定、可靠:可发送包含未知字符的内容。
容易产生的误区:HTTP 协议里并没有限制 GET 和 POST 的长度,GET 的最大长度限制是因为浏览器和 Web 服务器对 URL 的长度限制,不同的浏览器和 Web 服务器限制的最大长度不一样,它们所限制的是整个 URL 的长度,而不仅仅是查询参数的数据长度。
Ajax扩展
jQuery 中的 Ajax
jQuery 是一个 JavaScript 工具库,它封装了 JavaScript 常用的功能代码,包括我们刚刚学完的 Ajax。
jQuery 中,Ajax 常见的请求方式有以下几种:
$.ajax(url, options)$.get(url, data, callback, dataType)$.post(url, data, callback, dataType)$.getJSON(url, data, callback)$.getScript(url, callback)- jQuery元素
.load(url, data, callback)
// 使用jQuery发起ajax请求
$.ajax("/statics/demosource/demo_get_json.php", {
//请求类型
type: "GET",
//要发送的数据
data: {
country: country,
city: city
},
//数据格式
dataType: "json",
//请求成功后执行
success: function (res) { // res为响应成功返回的数据
oIpt_country.innerText = res.params.country;
oIpt_city.innerText = res.params.city;
},
//请求失败后执行
error: function (res) { // 这里的res为响应失败返回的数据
alert("请求失败:" + res.status);
}
});
Ajax 的替代品:fetch
Fetch API 是随 ES6 发展而出现的一个 JavaScript 原生接口,与 Ajax 一样允许开发者异步发起 HTTP 请求,但却以更加简单明了的调用方式、基于 Promise 的数据处理方式被称作是 Ajax 的替代品。
fetch("/statics/demosource/demo_json_data.php", {
method: "POST",
header: new Headers({"Content-Type" : "application/json"}),
body: JSON.stringify(data)
})
.then(function (res) {
return res.ok ? res.json() : Promise.reject(res);
})
.then(function (data) {
oIpt_country.innerText = data.country;
oIpt_city.innerText = data.city;
})
.catch(function (res) {
alert("请求失败:" + res.status);
})
JSON
JSON = JavaScript Object Notation,意思是:JavaScript 对象表示法,是一种轻量级的数据交换格式。
语法规则
JSON 的语法可以表示以下三种类型的值:
- 简单值:使用与 JavaScript 相同的语法,可以在 JSON 中表示
number、string、boolean与null,但 JSON 不支持 JavaScript 中的特殊值undefined; - 对象:对象作为一种复杂数据类型, 表示的是一组无序的键值对,而每个键值对中的值可以是简单值,也可以是复杂数据类型的值;
- 数组:数组也是一种复杂数据类型,表示一组有序的值的列表,数组的值也可以是任意类型 —— 简单值、对象 或 数组。
简单值
//JSON 表示数值 7
7
//JSON 表示字符串
"JSON is a format for data exchange"
注意:
JSON字符串 与 JavaScript字符串 的最大区别在于,JSON 字符串必须使用 双引号,单引号会导致语法错误。
对象
JSON 中的对象与 JavaScript 对象字面量稍微有一些不同。
JavaScript 的对象字面量:
{
name : "Alan",
age : 21
}
json表示
{
"name" : "Alax",
"age" : 21
}
JSON 对象的键(属性名) 必须 加 双引号。
JSON 对象的属性值可以是简单值,也可以是复杂类型值
{
"name" : "Alan",
"age" : 21,
"child" : {
"name" : "Tim",
"age" : 7
}
}
数组
JSON 数组采用的就是 JavaScript 中的数组字面量形式。
JavaScript 中的数组字面量:
[21, "Alan", false]
json表示
[21, "Alan", false]
总结
- 对于 JSON 与 JavaScript 的关系,你现在可以这么理解:JSON 是 JavaScript 对象的字符串表示法,它使用纯文本格式来表示一个 JavaScript 对象的信息,本质上是一个字符串;
- 通常,我们会将对象和数组作为 JSON 数据结构的最外层形式,利用它们能够创造出各种各样的数据结构。当然,这不是强制规定的。
JavaScript 内置的 JSON 对象
ECMAScript 5 定义了一个原生的 JSON 对象,可把 JavaScript 对象序列化为 JSON 字符串,或把 JSON 字符串解析为原生的 JavaScript 值。
JSON 对象的方法:
JSON.stringify():用于序列化 JavaScript 对象,将其转换为 JSON 字符串;JSON.parse():用于解析 JSON 字符串,将其转换为 JavaScript 值。
提示:除了以上两个方法,JSON 对象本身并没有其它作用,也不能被做为构造函数使用。
stringify 方法
JSON.stringify()方法用于将一个 JavaScript 值 / 对象 转换为 JSON 字符串。
var obj = {
name: "Alan",
age: 21,
child: {
name: "Tim",
age: 7
}
};
// 序列化 obj 对象,转换为 JSON 格式的字符串
var json = JSON.stringify(obj)
parse 方法
JSON.parse()方法用于将 JSON 数据解析为原生的 JavaScript 值。
var json = '{"name":"Alan","age":21,"child":{"name":"Tim","age":7}}';
// json 数据本质上是字符串,无法直接访问某一属性
console.log(json.name); // undefined
// 解析 json,转换为原生的 JavaScript 对象
var obj = JSON.parse(json);
console.log(obj.name); // 此时可以使用 JavaScript 方法访问某一属性