目標
/*
1. 說出什麼是前後端互動模式
2. 說出Promise的相關概念和用法
3. 使用fetch進行介面呼叫
4. 使用axios進行介面呼叫
5. 使用asynnc/await方式呼叫介面
6. 基於後臺介面實現案例
*/
前後端互動模式
介面呼叫方式
/*
原生ajax
基於jQuery的ajax
fetch
axios
*/
傳統形式的URL
/*
格式: schema://host:port/path?query#fragment
1. schema: 協議. 例如http,https,ftp等
2. host: 域名或者IP地址
3. port: 埠,http預設埠80,可以省略
4. path: 路徑,例如/abc/a/b/c
5. query: 查詢引數uname=list&age=12
6. fragment: 錨點(雜湊Hash),用於定位頁面某個位置
*/
Restful形式的URL
/*
HTTP請求方式
1. GET 查詢
2. POST 新增
3. PUT 修改
4. DELETE 刪除
*/
Promise
傳統js非同步呼叫
非同步呼叫分析
/*
1. 定時任務
2. Ajax
3. 事件函式
*/
多次非同步呼叫的依賴分析
/*
多次非同步呼叫的結果順序不確定
非同步呼叫結果如果存在依賴需要巢狀
*/
Example(傳統ajax)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {},
methods: {}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>前後端互動</div>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
/*
前後端互動,非同步程式設計與Promise概述
*/
var ret = '---'
$.ajax({
url: 'http://localhost:3000/data',
success: function (data) {
ret = data
console.log(ret)
}
});
console.log(ret)
</script>
</body>
</html>
Promise概述
Promise是非同步程式設計的一種解決方案,從語法上講,Promise是一個物件,從他可以獲取非同步操作的資訊.
Promise好處
/*
使用Promise主要有以下好處:
可以避免多層非同步呼叫巢狀問題(回撥地獄)
Promise物件提供了簡介的API,使得控制非同步操作更加容易
*/
Promise使用
/*
基本用法
例項化Promise物件,建構函式中傳遞函式,該函式用於處理非同步任務.
resolv和reject兩個引數用於處理成功和失敗兩種情況,並通過p.then獲取處理結果.
*/
var p = new Promise(function(resolve,reject){
// 成功時呼叫 resolve()
// 失敗時呼叫 reject()
p.then(function(ret){
// 從resolve得到正常結果
},function(ret){
// 從reject得到錯誤資訊
});
});
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {},
methods: {}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>前後端互動</div>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
/*
Promise基本使用
*/
var p = new Promise(function (resolve, reject) {
// 這裡用於實現非同步任務
setTimeout(function () {
var flag = false;
if (flag) {
// 正常情況
resolve('hello');
} else {
// 異常情況
reject('500');
}
}, 100);
});
p.then(function (data) {
console.log(data)
}, function (info) {
console.log(info)
})
</script>
</body>
</html>
處理原生Ajax
function queryData(){
return new Promise(function(resolve,reject){
var xhr - new XMLHttpRequest();
xhr.cnreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.status == 200){
resolve(xhr.responseText)
}else{
reject('出錯了');
}
}
xhr.open('get','/data');
xhr.send(null);
})
}
處理多次Ajax請求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {},
methods: {}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>前後端互動</div>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
/*
基於Promise傳送Ajax請求
*/
function queryData(url) {
var p = new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
// 處理正常情況
resolve(xhr.responseText);
} else {
// 處理異常情況
reject('伺服器錯誤');
}
};
xhr.open('get', url);
xhr.send(null);
});
return p;
}
// queryData('http://localhost:3000/data')
// .then(function(data){
// console.log(data)
// },function(info){
// console.log(info)
// });
// 傳送多個Ajax請求並且保證順序
queryData('http://localhost:3000/data')
.then(function (data) {
console.log(data)
return queryData('http://localhost:3000/data1');
})
.then(function (data) {
console.log(data);
return queryData('http://localhost:3000/data2');
})
.then(function (data) {
console.log(data)
});
</script>
</body>
</html>
then引數中的函式返回值
/*
1. 返回Promise例項物件
返回的該例項物件會呼叫下一個then
2. 返回普通值
返回的普通值會直接傳遞給下一個then,通過then引數中函式的引數接受該值
*/
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
then引數中的函式返回值
*/
function queryData(url) {
return new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200) {
// 處理正常的情況
resolve(xhr.responseText);
}else{
// 處理異常情況
reject('伺服器錯誤');
}
};
xhr.open('get', url);
xhr.send(null);
});
}
queryData('http://localhost:3000/data')
.then(function(data){
return queryData('http://localhost:3000/data1');
})
.then(function(data){
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve(123);
},1000)
});
})
.then(function(data){
return 'hello';
})
.then(function(data){
console.log(data)
})
</script>
</body>
</html>
Promise常用API
/*
例項方法
p.then() 得到非同步任務的正確結果
p.catch() 獲取異常資訊
p.finally() 成功與否都會執行(尚且不是正式標準)
queryData()
.then(function(data){
console.log(data);
})
.catch(function(data){
console.log(data);
})
.finally(function(){
console.log('finished');
});
*/
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
Promise常用API-例項方法
*/
// console.dir(Promise);
function foo() {
return new Promise(function(resolve, reject){
setTimeout(function(){
// resolve(123);
reject('error');
}, 100);
})
}
// foo()
// .then(function(data){
// console.log(data)
// })
// .catch(function(data){
// console.log(data)
// })
// .finally(function(){
// console.log('finished')
// });
// --------------------------
// 兩種寫法是等效的
foo()
.then(function(data){
console.log(data)
},function(data){
console.log(data)
})
.finally(function(){
console.log('finished')
});
</script>
</body>
</html>
物件方法
/*
Promise.all() 併發處理多個非同步任務,所有任務都執行成功才能得到結果
Promise.race() 併發處理多個非同步任務,只要有一個任務完成就能得到結果
*/
Promise.all([p1,p2,p3]).then((result) =>{
console.log(result)
})
Promise.race([p1,p2,p3]).then((result) =>{
console.log(result)
})
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
Promise常用API-物件方法
*/
// console.dir(Promise)
function queryData(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
// 處理正常的情況
resolve(xhr.responseText);
} else {
// 處理異常情況
reject('伺服器錯誤');
}
};
xhr.open('get', url);
xhr.send(null);
});
}
var p1 = queryData('http://localhost:3000/a1');
var p2 = queryData('http://localhost:3000/a2');
var p3 = queryData('http://localhost:3000/a3');
// Promise.all([p1,p2,p3]).then(function(result){
// console.log(result)
// })
Promise.race([p1, p2, p3]).then(function (result) {
console.log(result)
})
</script>
</body>
</html>
fetch請求元件
fetch
XMLHttpRequest是一個設計粗糙的API, 配置和呼叫方式非常混亂,而且基於事件的非同步模型寫起來不友好,相容性不好.
基本特性
/*
更加簡單的資料獲取方式,功能更強大,更靈活,可以看做是xhr升級版
基於Promise實現
*/
基本用法
Example
fetch('/abc').then(data=>{
return data.text();
}).then(ret=>{
// 注意這裡得到的才是最終的資料
console.log(ret);
})
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {},
methods: {}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
Fetch API基本用法
*/
fetch('http://localhost:3000/fdata').then(function (data) {
// text() 方法屬於fetchAPI的一部分,他返回一個Promise例項物件,用於獲取後臺返回資料
return data.text();
}).then(function (data) {
// 這裡得到的才是最終的資料
console.log(data);
})
</script>
</body>
</html>
Example2
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<button @click="handleClick()">獲取影片資訊</button>
<ul>
<li v-for="data in datalist">
<h3>{{ data.name }}</h3>
<img :src="data.poster">
</li>
</ul>
</div>
<script>
new Vue({
el: "#box",
data: {
datalist: []
},
methods: {
handleClick() {
fetch("./json/test.json").then(res => res.json()).then(res => {
console.log(res.data.films)
this.datalist = res.data.films
})
}
}
})
</script>
<!-- new Vue({
el: "#box",
data:{
datalist:["111","222","333"]
}
}) -->
</body>
</html>
fetch請求引數
常用配置選項
/*
method(String): HTTP請求方法,預設為GET(GET,POST,PUT,DELETE)
body(String): HTTP的請求引數
headers(Object) HTTP的請求頭,預設為{}
*/
GET請求方式的引數傳遞
fetch('/abc?id=123').then(data=>{
return data.text();
}).then(ret=>{
// 注意這裡得到的才是最終的資料
console.log(ret)
})
fetch('/abc/123',{
method 'get'
}).then(data=>{
return data.text();
}).then(ret=>{
// 注意這裡得到的才是最終的資料
console.log(ret);
});
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {},
methods: {}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
/*
Fetch API: 呼叫介面傳遞引數
*/
// fetch('http://localhost:3000/books?id=123',{
// method: 'get'
// })
// .then(function (data) {
// return data.text();
// }).then(function (data) {
// console.log(data)
// });
fetch('http://localhost:3000/books/123',{
method: 'get'
})
.then(function (data) {
return data.text();
}).then(function (data) {
console.log(data)
});
</script>
</body>
</html>
POST請求方式引數傳遞
fetch('/books',{
method: 'post',
body: 'uname=list&pwd=123',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
}).then(data=>{
return data.text();
}).then(ret=>{
console.log(ret);
})
fetch響應結果
響應資料格式
/*
text(): 將返回體處理成字串型別
json(): 返回結果和JSON.parse(responseText)一樣
*/
fetch('/abc' then(data=>{
// return data.text();
return data.json();
}),then(ret=>{
console.log(ret);
});
axios請求元件
axios基本特性
/*
axios是一個基於Promise用於瀏覽器和node.js的HTTP客戶端.
具有以下特徵:
支援瀏覽器和node.js
支援promise
能攔截請求和響應
自動轉換JSON資料
*/
axios基本用法
axios.get('/adata')
.then(ret=>{
// data屬性名稱是固定的,用於獲取後臺響應的資料
console.log(ret.data)
})
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
axios.get('http://localhost:3000/adata').then(function (ret) {
// 注意data屬性是固定的用法,用於獲取後臺的實際資料
console.log(ret.data)
})
</script>
</body>
</html>
axios的常用api
GET傳遞引數
/*
通過URL傳遞引數
通過params選項傳遞引數
*/
Exmaple2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
// axios.get('http://localhost:3000/axios?id=1234').then(function (ret) {
// // 注意data屬性是固定的用法,用於獲取後臺的實際資料
// console.log(ret.data)
// })
axios.get('http://localhost:3000/adata', {
params: {
id: 700
}
})
.then(function (ret) {
console.log(ret.data)
})
// axios.get('http://localhost:3000/axios/1234').then(function (ret) {
// // 注意data屬性是固定的用法,用於獲取後臺的實際資料
// console.log(ret.data)
// })
</script>
</body>
</html>
POST傳遞引數
通過選項傳遞引數(預設傳遞的是json格式的資料)
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
axios.post('http://localhost:3000/axios', {
uname: 'lisi',
pwd: 123
}).then(function(ret){
console.log(ret.data)
})
</script>
</body>
</html>
通過URLSearchParams傳遞引數(application/x-www-form-urlencoded)
Example2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
var params = new URLSearchParams();
params.append('uname','youmen');
params.append('pwd','123');
axios.post('http://localhost:3000/axios',params).then(function(ret) {
console.log(ret.data)
})
</script>
</body>
</html>
axios的響應結果
/*
data: 實際響應回來的資料
header: 響應頭資訊
status: 響應狀態碼
statusText: 響應狀態資訊
*/
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
/*
axios 響應式結果與全域性配置
*/
axios.get('http://localhost:3000/axios-json').then(function(ret) {
console.log(ret.data)
})
</script>
</body>
</html>
axios的全域性配置
/*
axios.default.timeout=3000; //超時時間
axios.defaults.baseURL='http://localhost:3000/app'; // 預設地址
axios.defaults.headers['mytoken'] = 'asadfjksdfjkdsaf' // 設定請求頭
*/
Example1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
/*
axios 響應式結果與全域性配置
*/
axios.defaults.baseURI = 'http://localhost:3000/';
// 設定頭資訊
axios.defaults.headers['mytoken'] = 'hello';
axios.get('axios-json').then(function(ret) {
console.log(ret)
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript" src="lib/vue.js"></script>
</head>
<body>
<div id="box">
<button @click="handleClick()">正在熱映</button>
<ul>
<li v-for="data in datalist">
<h1>{{ data.name }}</h1>
<img :src="data.poster">
</li>
</ul>
</div>
<script>
new Vue({
el: "#box",
data: {
datalist: []
},
methods: {
handleClick() {
axios.get("./json/test.json").then(res => {
// axios 自歐東包裝data屬性 res.data
console.log(res.data.data.films)
this.datalist = res.data.data.films
}).catch(err => {
console.log(err);
})
}
}
})
</script>
</body>
</html>