出了點小 bug, 爲啥後面的 post 請求, Flask 都接收不到
一、後端 API 服務搭建
爲了方便我採用 Python Flask 編寫 API,如果有其他 api 服務搭建的同學,可以移步:四種方式搭建 API,總有一款適合你
編寫 Flask 程序應用框架
#!/usr/bin/python
# -*- coding: utf-8 --
#@File: app.py
#@author: Gorit
#@contact: [email protected]
#@time: 2020/5/9 11:58
from flask import Flask, request
app = Flask(__name__)
# 解決跨域問題
@app.after_request
def cors(environ):
environ.headers['Access-Control-Allow-Origin']='*'
environ.headers['Access-Control-Allow-Method']='*'
environ.headers['Access-Control-Allow-Headers']='x-requested-with,content-type'
return environ
@app.route("/data")
def data():
return "Hello World"
if __name__ == '__main__':
app.run(port=3000,debug=True)
項目成功 跑起來了
二、原生 ajax
原生的 ajax 是基於 XMLhttpRequest 進行數據傳輸的,關於什麼是 ajax,可以看這兩篇解釋,以及基本使用
原生 ajax 實現 (這個調試花了我好久時間)
原生 ajax + Java EE 實現用戶驗證功能
原生 ajax + Java EE 實現二級菜單聯動
原生的 ajax 代碼量過長,我在這裏就不在演示了,這裏我使用 Jquery 完成原生的 ajax 操作
2.1 不帶參數的 get 請求
後端接口編寫
# 解決跨域請求問題,後面就不帶這個了
@app.after_request
def cors(environ):
environ.headers['Access-Control-Allow-Origin']='*'
environ.headers['Access-Control-Allow-Method']='*'
environ.headers['Access-Control-Allow-Headers']='x-requested-with,content-type'
return environ
# 不帶參數的 get 請求
@app.route("/ajax/data")
def ajax():
return '我收到了 ajax 的請求'
前端 js
<script>
// get 請求
$.ajax({
url: "http://127.0.0.1:3000/ajax/data",
type: "get",
success: function(msg) {
console.log(msg);
}
})
</script>
成功響應
2.2 帶參數的 get 請求
後端接口編寫
# 帶參數的 get 請求
@app.route("/ajax/data1")
def ajax1():
# Flask 獲取 get 請求參數的方式
uname = request.args.get("uname")
pwd = request.args.get("pwd")
print(uname,pwd)
return f"get 請求的參數:uname:{uname}, pwd:{pwd}"
後端響應
前端 js
// 帶參數的 get 請求
$.ajax({
url: "http://127.0.0.1:3000/ajax/data1",
type: "get",
data: {
"uname": "cici",
"pwd":123456
},
success: function(msg) {
console.log(msg);
}
})
前端響應結果
2.3 帶參數的 post 請求
後端 API 編寫
@app.route("/ajax/post",methods=['POST'])
def post():
# Flask 獲取 post 參數
uname = request.form.get("uname")
pwd = request.form.get("pwd")
print(uname,pwd)
return f"post 請求的參數:uname:{uname}, pwd:{pwd}"
後端響應
前端 js
// 帶參數的 post 請求
$.ajax({
url: "http://127.0.0.1:3000/ajax/post",
type: "post",
data: {
"uname": "cici",
"pwd":123456
},
success: function(msg) {
console.log(msg);
}
})
前端響應
2.4 get 請求返回 json 數據
後端接口編寫
@app.route("/ajax/js")
def ajax_json():
person = {"id":3324,"username":"coco","password":'3329wdadwda',"hobbies":["籃球","唱歌","跳舞"]}
return jsonify(person)
可以看到也面返回了 JSON 格式的數據
前端 js
// 獲取 json 數據
$.ajax({
url: "http://127.0.0.1:3000/ajax/js",
type: "get",
dataType:"json",
success: function(msg) {
console.log(msg);
}
})
數據正常響應了
三、原生 Promise
3.1 什麼是 Promise?
Promise 是異步編程的解決方案,是一個對象,可以獲取異步操作的信息,可以看做是 ajax 的升級版,這個可以直接使用,不需要引入 第三方包
3.2 Promise 的基本使用
- 實例化 Promise 對象。構造函數中傳遞函數,該函數用於處理異步任務
- resolve 和 reject 兩個參數用於處理成功和失敗的兩種情況,並通過 p.then 獲取處理結果
<script>
console.log(typeof Promise);
let p = new Promise(function(resolve,reject){
// 成功調用 resolve
// 失敗調用 reject
setTimeout(function(){
let flag = true;
if (flag) {
// 正常情況
resolve('hello');
} else {
reject('出錯了');
}
},100);
});
p.then(function(data){
// 從 resolve 得到正常結果
console.log(data);
},function(info) {
// 從 reject 得到結果
console.log(info);
});
</script>
3.3 使用 Promise 發起 ajax 請求
編寫 Promise 的測試案例的後臺接口
@app.route("/data")
def data():
return "Hello World"
@app.route("/data1")
def data1():
return "Hello Tom"
@app.route("/data2")
def data2():
return "Hello Jerry"
js 處理
<script>
// 基於 Promise 發起 Ajax 請求,這裏我們使用 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);
});
// then 的返回值情況
// 1. then 返回 Promise 實例對象,調用下一個 then,
// 2. 第二種,直接在 then 返回 具體值,下一個 then 皆可以得到具體的值
return p;
}
queryData('http://127.0.0.1:3000/data')
.then(function(data) {
// 執行成功
console.log(data);
},function(info) {
// 執行失敗
console.log(info);
});
// 發送多個 ajax 請求,並且保證順序, 解決回調地獄問題,then 就很好的解決了
queryData('http://127.0.0.1:3000/data')
.then(function(data) {
// 執行成功
console.log(data);
return queryData("http://127.0.0.1:3000/data1");
})
.then(function(data) {
// 執行成功
console.log(data);
return queryData("http://127.0.0.1:3000/data2");
// return hello
})
.then(function(data) {
// 執行成功
console.log(data);
});
</script>
結果:
3.4 Promise API
- p.then() 得到異步正常結果
- p.catch() 捕獲異常(等價於得到 reject 的返回值)
- p.finally() 不管成功,失敗都會執行
js 處理
<script>
// p.then() 得到異步正常結果
// p.catch() 捕獲異常
// p.finally() 不管成功,失敗都會執行
function foo() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
// resolve('123'); // then 接收
reject('error'); //catch 接收
},100);
})
}
// foo()
// .then(function(data) {
// console.log(data); // 打印 123
// })
// .catch(function(data) {
// console.log(data);
// })
// .finally(function() {
// console.log('finished')
// })
// 兩種編寫方式等價
foo()
.then(function(data) {
console.log(data); // 打印 123
}, function(data) {
console.log(data);
})
.finally(function() {
console.log('finished')
})
</script>
四、fetch api
fetch 是 Promise 和 xmlHttpRequest 的升級版,使用起來會更加的便捷
4.1 fetch 基本使用
後端 api 搭建
@app.route('/fdata')
def fdata():
return 'Hello Fetch'
前端 js
<!-- 基於 Promise, xhr 升級版本 -->
<script type="text/javascript">
fetch('http://127.0.0.1:3000/fdata').then(function(data) {
// text() 方法屬於 fetchAPI 的一部分 它返回 promise 實例對象, 所以要通過返回 data.text() 得到服務器的返回數據,data.json() 則返回json 數據
console.log(data);
return data.text();
}).then(function(data) {
console.log(data);
});
// 返回 JSON,這裏用到了前面編寫的 JSON API
fetch('http://127.0.0.1:3000/ajax/js').then(function(data) {
return data.json();
}).then(function(data) {
console.log(data);
});
</script>
前端響應結果
4.2 fetch 發起帶參數的 get 請求
接口前面有寫過,這裏只寫前端
<script>
// 指定返回類型
// 1. data.text() 字符串
// 2. data.json() 返回JSON ,同 JSON.parse(responseText)
fetch('http://127.0.0.1:3000/ajax/data1?uname=123&pwd=223')
.then(function(data) {
return data.text();
}).then(function(res) {
console.log(res);
});
</script>
4.3 fetch 發起post 請求,並帶參數
fetch('http://127.0.0.1:3000/ajax/post', {
method: 'POST',
body: {
"uname":123,
"pwd":223
}
})
.then(function(data) {
return data.text();
}).then(function(res) {
console.log(res);
});
但是遇到 小 BUG了
4.4 fetch 發送 get 請求, 返回 JSON 數據
// 返回 JSON,這裏用到了前面編寫的 JSON API
fetch('http://127.0.0.1:3000/ajax/js').then(function(data) {
return data.json();
}).then(function(data) {
console.log(data);
});
四、更好的封裝 axios?
axios 在 vue 中使用的會比較多,也是一個 第三方的 http 請求庫,可以在 Github 中找得到。
axios 是一個基於 Promise 用於遊覽器和 node.js 的客戶端
它具有以下特徵
- 支持遊覽器和 node.js
- 支持 promise
- 能攔截請求和相應
- 自動轉換 JSON 語句
4.1 axios 的基本使用
我們需要在使用之前引入 axios 庫
後端 api 的編寫
@app.route('/adata')
def adata():
return 'Hello axios'
// 語法使用
axios.get('/data')
.then(function(res) {
// data 屬性名是固定的,用於相應後臺數據
console.log(res.data);
})
// 最簡單的 axios 使用,通過 .data 獲取數據,固定用法
axios.get('http://localhost:3000/adata').then(function(res) {
console.log(res.data);
})
4.2 axios 常用 API
4.2.1 get 請求
後端 API 編寫
@app.route('/axios')
def axiod():
id = request.args.get("id")
return f'axios 傳遞參數 {id}'
# 獲取 restfull 參數
@app.route("/axios1/<int:id>")
def axios(id):
return f'axios1 restfull 傳遞參數 {id}'
@app.route('/axios2')
def axios2():
id = request.args.get("id")
name = request.args.get("name")
return f"axios2 傳遞的名稱:{name}, id 爲:{id}"
js 編寫
axios.get('http://localhost:3000/axios?id=132').then(function(res) {
console.log(res.data);
})
// restfull
axios.get('http://localhost:3000/axios1/223').then(function(res) {
console.log(res.data);
})
axios.get('http://localhost:3000/axios2', {
params: {
"id": 123,
"name": "coco"
}
}).then(function(res) {
console.log(res.data);
})
前端響應結果
4.2.2 post 請求
還找找 bug