05 . Vue前端交互,fetch,axios,以asyncawait方式调用接口使用及案例

目标javascript

/*
		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异步调用

异步调用分析html

/*
		1. 定时任务
		2. Ajax
		3. 事件函数
*/

屡次异步调用的依赖分析vue

/*
		屡次异步调用的结果顺序不肯定
		异步调用结果若是存在依赖须要嵌套
*/

Example(传统ajax)java

<!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是一个对象,从他能够获取异步操做的信息.node

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获得错误信息
  });
});

Example1jquery

<!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请求ios

<!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参数中函数的参数接受该值
*/

Exampleajax

<!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');
			});
*/

Example1chrome

<!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>

对象方法npm

/*
		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>