一、前后端交互基础
1、概念
什么是前后端交互?其实就是指前端通过接口,向后端发送请求,后端接收到请求之后,返回相应的数据,前端接收到数据后,再根据数据的内容,做出相应的展示或跳转的这个过程,就是前后端交互的过程。接口是由后端定义书写,前端只需要知道相应接口的请求方式、请求地址、携带参数等信息,然后通过特定的方式调用接口即可。
2、前端调用接口的方式
原生ajax
代码繁琐,调用麻烦,不常用。
基于jQuery的ajax
对 ajax 的二次封装,简化了很多代码,但目前也很少用。
fetch
是 ajax + Promise的结合,使用的方式和 jquery 提供的 $.ajax() 差不多。
axios(最常用)
是一个第三方库,语法简单,调用方便,基于Vue的项目最常用的一种方法。
二、Promise
1、概念
promise 的出现主要是为了解决回调地狱的问题,它可以将异步操作队列化,使各种异步操作能按照我们开发者期望的顺序去执行,并返回预期的结果,而且还可以在对象间传递和操作 promise,帮助我们处理队列。
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的API 接口,使得控制异步操作更加容易。当然也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
promise 对象代表一个异步操作,它有三种状态:① pending:初始状态 。 ② fulfilled:操作完成。 ③ rejected:操作失败。
2、基本使用
<script type="text/javascript">
/*
1. Promise基本使用
我们使用new来构建一个Promise Promise的构造函数接收一个参数,是函数,函数体的内容就是要执行的异步任务,并且传入两个参数:resolve,reject, 分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数
*/
var p = new Promise(function(resolve, reject){
//2. 这里创建异步任务 setTimeout
setTimeout(function(){
var flag = false;
if(flag) {
//3. 正常情况
resolve('hello');
}else{
//4. 异常情况
reject('出错了');
}
}, 100);
});
// 5 Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数
p.then(function(data){
// 第一个函数 对应 resolve
console.log(data)
},function(info){
// 第二个函数 对应 reject
console.log(info)
});
</script>
3、基于 promise 发送 ajax 请求
① 发送单个 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);
});
return p;
}
// 调用 Promise 对象
queryData('http://localhost:3000/data').then(function(data){
console.log(data);
},function(info){
console.log(info)
});
② 发送多个 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);
});
return p;
}
// 发送多个ajax请求并且保证顺序
queryData('http://localhost:3000/data').then(function(data){
console.log(data)
// 后面的 then 接收的是这个 promise 对象返回的值
return queryData('http://localhost:3000/data1');
})
.then(function(data){
console.log(data);
// 后面的 then 接收的是这个 promise 对象返回的值
return queryData('http://localhost:3000/data2');
})
.then(function(data){
console.log(data)
});
4、Promise 的 then() 函数的返回值
在then方法中,你可以直接return Promise对象,也可以return数据,在后面的then中就可以接收到数据了 。
// 以上面的代码为例
// 发送多个ajax请求并且保证顺序
queryData('http://localhost:3000/data').then(function(data){
console.log(data)
// 后面的 then 接收的是这个 promise 对象返回的值
return queryData('http://localhost:3000/data1');
})
.then(function(data){
console.log(data);
// 后面的 then 接收的是这个 'aaa' 数据
return 'aaa';
})
.then(function(data){
console.log(data) // aaa
});
5、Promise 的基本API
实例方法:
① then(函数1,[函数2])
该方法用来接收异步任务执行的结果。如果参数只有一个函数,则该函数只接受异步任务正确执行的结果。如果参数有两个,则第一个函数接收正确的结果,第二个函数接收出错的结果。最常用的还是then()。
② catch(函数)
该方法用来接收异步任务执行出错的结果。在then() 只接收正确的结果时,出错的结果则用该方法接收。不常用。
③ finally(函数)
无论异步任务执行正确或出错,该方法都会被调用。不常用。
案例代码:
/*
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')
});
对象方法:
① all()
该方法用来执行多个 promise 对象实例,并同时返回这些的对象实例的结果。参数为一个数组,数组元素是要执行的 promise 对象(如果不是一个promise,该项会被用Promise.resolve
转换为一个promise)。返回结果也是一个数组,数组元素是 promise 对象实例的执行结果,顺序与参数数组顺序一一对应。该方法的返回结果必须等到最后一个异步任务执行完后,再返回。
② race()
该方法与 all() 方法类似,也是用来执行多个 promise 对象实例,不同的是该方法的返回结果只有第一个执行结束的 promise 对象实例的结果,其他对象实例的结果被丢掉。
案例代码:
/*
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){
// all 中的参数 [p1,p2,p3] 和 返回的结果一 一对应["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"]
console.log(result) //["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"]
})
Promise.race([p1,p2,p3]).then(function(result){
// 由于p1执行较快,Promise的then()将获得结果'P1'。p2,p3仍在继续执行,但执行结果将被丢弃。
console.log(result) // "HELLO TOM"
})