都0202年了,你還不會前後端交互嗎


出了點小 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 的基本使用

  1. 實例化 Promise 對象。構造函數中傳遞函數,該函數用於處理異步任務
  2. 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

  1. p.then() 得到異步正常結果
  2. p.catch() 捕獲異常(等價於得到 reject 的返回值)
  3. 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 的客戶端
它具有以下特徵

  1. 支持遊覽器和 node.js
  2. 支持 promise
  3. 能攔截請求和相應
  4. 自動轉換 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章