都0202年了,你还不会先后端交互吗


出了点小 bug, 为啥后面的 post 请求, Flask 都接收不到

1、后端 API 服务搭建

为了方便我采用 Python Flask 编写 API,若是有其余 api 服务搭建的同窗,能够移步:四种方式搭建 API,总有一款适合你javascript

编写 Flask 程序应用框架前端

#!/usr/bin/python
# -*- coding: utf-8 --
#@File: app.py
#@author: Gorit
#@contact: gorit@qq.com
#@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)

项目成功 跑起来了
在这里插入图片描述vue

2、原生 ajax

原生的 ajax 是基于 XMLhttpRequest 进行数据传输的,关于什么是 ajax,能够看这两篇解释,以及基本使用java

原生 ajax 实现 (这个调试花了我很久时间)
原生 ajax + Java EE 实现用户验证功能
原生 ajax + Java EE 实现二级菜单联动node

原生的 ajax 代码量过长,我在这里就不在演示了,这里我使用 Jquery 完成原生的 ajax 操做python

2.1 不带参数的 get 请求

后端接口编写ios

# 解决跨域请求问题,后面就不带这个了
@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 的请求'

前端 jsweb

<script>
		// get 请求
		$.ajax({
			url: "http://127.0.0.1:3000/ajax/data",
			type: "get",
			success: function(msg) {
				console.log(msg);
			}
		})
	</script>

成功响应
在这里插入图片描述ajax

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);
		}
	})

数据正常响应了
在这里插入图片描述

3、原生 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>

4、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);
	});

4、更好的封装 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