協(xié)議(基于tcp/ip)
超文本傳輸協(xié)議(HyperText Transfer Protocol拘荡,HTTP)是用于從WWW服務(wù)器傳輸超文本到本地瀏覽器的傳輸協(xié)議 (transport)台丛。它可以使瀏覽器更加高效,使網(wǎng)絡(luò)傳輸減少秆撮。
請求的類型
同步請求 (上一個請求沒完成 不能進(jìn)行其他操作)
<a >去百度</a>
<a >去微博</a>
異步請求 (上一個請求沒完成和下一個操作沒有關(guān)系)
setIterval(()=>{
console.log('123')
},10)
button.onclick = function(){
setTimeout(()=>{
console.log('按鈕1被點擊了')
},1000)
}
div.onclick = function(){
console.log('div被點擊了')
}
線程和進(jìn)程
線程 是進(jìn)程一個組成(最小計量單位)(多個影片下載每個都是一個單獨的線程)
進(jìn)程 進(jìn)行程序叫做進(jìn)程(打開愛奇藝 產(chǎn)生一個愛奇藝的進(jìn)程)
ajax概述
ajax (全稱 Asynchronous Javascript And Xml )譯為 異步的js和xml。它是用來異步請求數(shù)據(jù)的(基于http)。它可以實現(xiàn)局部的加載變化蛉加。js來進(jìn)行請求的 攜帶的數(shù)據(jù)類型和返回的數(shù)據(jù)類型為xml形式(早期)同衣。
ajax主要依賴的是一個請求對象 核心對象 xmlHttpRequest
注意:使用XMLHttpRequest時竟块,必須把文件放到Web服務(wù)器上。因為AJAX只能向同源網(wǎng)址(協(xié)議耐齐、域名浪秘、端口都相同)發(fā)出HTTP請求,如果發(fā)出跨源請求埠况,就會報錯
ajax的訪問流程
- 創(chuàng)建請求對象(XMLHttpRequest)
- 打開指定的請求地址 指定對應(yīng)的請求方式 (open)
- 帶參數(shù) 設(shè)置請求頭
- 開始請求 (send)
- 監(jiān)聽對應(yīng)的請求狀態(tài)的變化
- 在監(jiān)聽中讀取對應(yīng)的響應(yīng)數(shù)據(jù) 并進(jìn)行處理
為了在響應(yīng)準(zhǔn)備就緒時得到通知耸携,我們必須監(jiān)聽XMLHttpRequest對象上的 readystatechange 事件。 每當(dāng)發(fā)生狀態(tài)變化的時候询枚,readyState屬性的值就會發(fā)生改變违帆。這個值每一次變化,都會觸readyStateChange事件金蜀。
代碼實現(xiàn)
//創(chuàng)建請求對象
var xhr = new XMLHttpRequest()
//調(diào)用open()方法并不會真正發(fā)送請求刷后,而只是啟動一個請求以備發(fā)送。
xhr.open('get', 'http://jsonplaceholder.typicode.com/todos')
//發(fā)送請求
xhr.send()
xhr.onreadystatechange = function () {
//5個變化 0 1 2 3 4 狀態(tài)碼 http的狀態(tài) 100-599(1開頭 表示成功但是需要下一步操作 2開頭表示成功 3開頭表示重定向 4開頭表示客戶端錯誤 5開頭表示服務(wù)器錯誤)
if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
//讀取數(shù)據(jù) responseText 返回給你是字符串 responseXML 返回給你的是xml
console.log(xhr.responseText)
}
}
readyState
readyState 是一個整數(shù)渊抄,它指定了HTTP請求的狀態(tài)尝胆。它可能的值如下:
0,對應(yīng)常量UNSENT护桦,表示XMLHttpRequest實例已經(jīng)生成含衔,但是open()方法還沒有被調(diào)用。
1,對應(yīng)常量OPENED贪染,表示open()已調(diào)用缓呛,但send()方法還沒有被調(diào)用,仍然可以使用setRequestHeader()杭隙,設(shè)定HTTP 請求的頭信息哟绊。
2,對應(yīng)常量HEADERS_RECEIVED痰憎,表示send()方法已經(jīng)執(zhí)行票髓,并且頭信息和狀態(tài)碼已經(jīng)收到。
3铣耘,對應(yīng)常量LOADING洽沟,表示正在接收服務(wù)器傳來的主體(body)部分的數(shù)據(jù),如果responseType屬性是text或者空字符串蜗细,responseText就會包含已經(jīng)收到的部分信息裆操。
-
4,對應(yīng)常量DONE鳄乏,表示服務(wù)器數(shù)據(jù)已經(jīng)完全接收跷车,或者本次接收已經(jīng)失敗了。
在IE8之前并沒有定義這些值橱野,但使用硬編碼值4來表示XMLHttpRequest.DONE朽缴。
status
status屬性為只讀屬性,表示本次請求所得到的HTTP狀態(tài)碼水援,它是一個整數(shù)密强。
- 200, OK,訪問正常
- 301, Moved Permanently蜗元,永久移動
- 302, Move temporarily或渤,暫時移動
- 304, Not Modified,未修改
- 307, Temporary Redirect奕扣,暫時重定向
- 401, Unauthorized薪鹦,未授權(quán)
- 403, Forbidden,禁止訪問
- 404, Not Found惯豆,未發(fā)現(xiàn)指定網(wǎng)址
- 500, Internal Server Error池磁,服務(wù)器發(fā)生錯誤
XMLHttpRequest存在兼容問題
var xhr = XMLHttpRequest ? new XMLHttpRequest() :new ActiveXObject("Microsoft.XMLHTTP")
http請求方式
get 請求 (默認(rèn)請求方式)
它是以?拼接進(jìn)行傳參
它的請求地址以及參數(shù)會暴露在地址(不安全)
get請求的數(shù)據(jù)不能超過2kb
get請求是有歷史記錄的(緩存的)可以后退的
post 請求 (必須請求方式為post 默認(rèn)傳參是表單傳參)
post請求的參數(shù)在請求體中被傳遞
post請求相對于get請求來說不會暴露在地址欄(安全較高)
post請求攜帶的數(shù)據(jù)要大于get請求
post請求沒有歷史記錄 (不能后退)
resetful 風(fēng)格的接口(后臺接口的風(fēng)格)
返回的數(shù)據(jù)以json格式傳遞 以請求方式來說區(qū)分對應(yīng)的后端處理業(yè)務(wù)
get請求 獲取操作 post請求添加操作 delete 刪除操作 put 修改操作(修改多個) patch 修飾(修改一個)
使用get請求對應(yīng)的數(shù)據(jù)并渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul></ul>
<script>
var xhr = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP")
//ajax在請求的時候 如果是get請求你需要帶參數(shù) 直接在地址后面將對應(yīng)的參數(shù)拼接 ?key=value&key1=value1
xhr.open('get', 'http://jsonplaceholder.typicode.com/todos?id=1')
xhr.send()
//通過回調(diào)函數(shù)來解決異步問題
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
let result = JSON.parse(xhr.responseText)
let ul = document.querySelector('ul')
//進(jìn)行渲染
result.forEach((item) => {
ul.innerHTML += `<li>
${item.title}
${item.completed ? '??': '??'}
</li>`
})
}
}
</script>
</body>
</html>
get請求封裝
//封裝get請求 請求地址 請求的參數(shù) 回調(diào)函數(shù)
static get(url,param={},callback){
if(!url){
throw new Error('url地址必須要填入')
}
//參數(shù)解析 ?key=value&key1=value1
// 遍歷param對象
for(let key in param){
//url里面如果存在?
if(url.includes('?')){
url += `&${key}=${param[key]}`
}else{
url += `?${key}=${param[key]}`
}
}
let xhr = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP")
xhr.open('get',url)
xhr.send()
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
let response = JSON.parse(xhr.responseText)
if(callback instanceof Function){
callback(response)
}
}
}
}
post示例
var xhr = new XMLHttpRequest()
xhr.open('post','https://jsonplaceholder.typicode.com/posts')
//注意:使用POST請求時,如果不設(shè)置Content-Type頭部信息楷兽,那么發(fā)送給服務(wù)器的數(shù)據(jù)就不會出現(xiàn)在 $_POST 中地熄。
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
xhr.send()
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
console.log(xhr.responseText)
}
}
登錄注冊案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<button>注冊</button>
<button>登錄</button>
<script>
//獲取對應(yīng)的輸入框的內(nèi)容 獲取按鈕
var inputs = document.querySelectorAll('input')
var btns = document.querySelectorAll('button')
//通過ajax去請求
//注冊
btns[0].onclick = function(){
var xhr = new XMLHttpRequest()
xhr.open('post','http://useker.cn/reg')
//指定對應(yīng)的請求頭
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
xhr.send(`uname=${inputs[0].value}&upwd=${inputs[1].value}&uage=${inputs[2].value}
&uphone=${inputs[3].value}&realname=${inputs[4].value}
`)
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
console.log(xhr.responseText);
alert(JSON.parse(xhr.responseText).msg)
}
}
}
//通過ajax去請求
//登錄
btns[1].onclick = function(){
var xhr = new XMLHttpRequest()
xhr.open('post','http://useker.cn/login')
//指定對應(yīng)的請求頭
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
xhr.send(`uname=${inputs[0].value}&upwd=${inputs[1].value}`)
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
console.log(xhr.responseText);
alert(JSON.parse(xhr.responseText).msg)
}
}
}
</script>
</body>
</html>
get請求和post請求在xhr請求的區(qū)別
get請求是使用?拼接url傳參的
xhr.open('get',url+'?key=value&key1=value1')
post通過send發(fā)送請求體的方式
xhr.send('key=value&key1=value1')
get請求不需要指定對應(yīng)的請求頭 post請求必須要指定請求頭
注意:必須在調(diào)用open()方法只會且調(diào)用send()方法之前調(diào)用setRequestHeader()。
xhr.setRequestHeader('content-type','x-www-form-urlencoded')
post請求的封裝
static post(url,param={},callback){
if(typeof url != 'string'){
throw new Error('url地址錯誤')
}
//參數(shù)解析
let responseStr = ''
// 遍歷param對象
for(let key in param){
//如果當(dāng)前的str為空字符串 那么就不需要& 否則前面需要&符號
if(responseStr){
responseStr += `&${key}=${param[key]}`
}else{
responseStr += `${key}=${param[key]}`
}
}
let xhr = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP")
xhr.open('post',url)
xhr.setRequestHeader('content-type','x-www-form-urlencoded')
xhr.send(responseStr)
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
let response = JSON.parse(xhr.responseText)
if(callback instanceof Function){
callback(response)
}
}
}
}
promise封裝
class Ajax{
constructor(){
}
//封裝get請求 請求地址 請求的參數(shù) 回調(diào)函數(shù)
static get(url,param={}){
if(!url){
throw new Error('url地址必須要填入')
}
//參數(shù)解析 ?key=value&key1=value1
// 遍歷param對象
for(let key in param){
//url里面如果存在?
if(url.includes('?')){
url += `&${key}=${param[key]}`
}else{
url += `?${key}=${param[key]}`
}
}
let xhr = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP")
xhr.open('get',url)
xhr.send()
return new Promise((resolve,reject)=>{
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
let response = JSON.parse(xhr.responseText)
resolve(response)
}
}
xhr.onerror = function(){
reject('請求錯誤')
}
})
}
static post(url,param={}){
if(typeof url != 'string'){
throw new Error('url地址錯誤')
}
//參數(shù)解析
let responseStr = ''
// 遍歷param對象
for(let key in param){
//如果當(dāng)前的str為空字符串 那么就不需要& 否則前面需要&符號
if(responseStr){
responseStr += `&${key}=${param[key]}`
}else{
responseStr += `${key}=${param[key]}`
}
}
let xhr = new XMLHttpRequest() || new ActiveXObject("Microsoft.XMLHTTP")
xhr.open('post',url)
xhr.setRequestHeader('content-type','x-www-form-urlencoded')
xhr.send(responseStr)
return new Promise((resolve,reject)=>{
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
let response = JSON.parse(xhr.responseText)
resolve(response)
}
}
xhr.onerror = function(){
reject('請求錯誤')
}
})
}
}