Promise的基本使用
Promise是异步编程的一种解决方案(说白了对异步操作进行封装)。那哪里需要用到异步呢?很常见的就是网络请求了
Promise是个类,创建实例时需要传递参数
参数:
resolve:是一个函数,在异步操作成功时进行回调then()
reject:是一个函数,在异步操作失败时进行回调catch()
tips: 以后基本所有异步的操作都在这两个函数中写。
状态:
pending:等待状态
fulfill:当我们主动调用了resolve,处于满足状态
reject:当我们主动调用了reject,处于拒绝状态
在下面的演示中都用setTimeout()来比作网络请求。
使用Promise的步骤:
一、创建Promise对象
new Promise((resolve,reject) => {})
创建Promise时的参数必须是一个函数,并且此函数会默认传resolve跟rejcet这两个函数。
二、使用Promise:
当异步请求成功时,我们需要手动调用resolve()函数,此时Promise会自动调用.then函数。失败时,手动调用reject()函数,此时Promise自动调用.catch函数。
new Promise((resolve,reject) => {
setTimeout(() => {
// resolve()
reject()
}, 1000);
}).then(() => {
console.log("异步请求成功时调用resolve")
}).catch(() => {
console.log("异步请求失败时调用reject")
})
当然了,如果想要传递参数也是可以的。
new Promise((resolve,reject) => {
setTimeout(() => {
// resolve('我是resolve传递的参数')
reject('我是reject传递的参数')
}, 1000);
}).then(data => {
console.log("一秒后我就出来了",data)
}).catch(err => { // 知道我的p为什么没有加括号吗,因为我是箭头函数啊
console.log("一秒后我就出来了",err)
})
以上写法也可以化简:(即catch省略,then跟catch合并)
new Promise((resolve,reject) => {
setTimeout(() => {
// resolve('我是resolve传递的参数')
reject('我是reject传递的参数')
}, 1000);
}).then(data => {
console.log("我是另一种形式",data)
},err => {
console.log("我是另一种形式",err)
})
Promise的链式结构
如果在一个网络请求中需要再向别的地方发送一个网络请求。这时就要用到Promise的链式结构.
所谓链式结构就是一层Promise之后再return一个Promise。一层又一层
new Promise((resolve,reject) => {
setTimeout(() => {
resolve()
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve()
}, 1000);
}).then(() => {
console.log('我是第二步打印的')
})
}, 1000);
}).then(() => {
console.log("第一步打印的是我")
})
上面的链式结构是什么鬼?太繁琐了吧。下面就来个升级版的。
new Promise((resolve,reject) => {
setTimeout(() => {
resolve('resolve传递的参数')
}, 1000);
}).then((p) => {
console.log("====我是第一步"+p)
return Promise.resolve(p + '11')
}).then((data) => {
console.log("====我是第二步",data)
})
看出跟上一个的区别了吗,这次的return是在then里面写的,而且还简化了。因为resolve跟reject这两个参数是可以省略的,所以可以把new Promise(...)
写成Promise.resolve
或者Promise.reject
的形式.
基操勿六,下面来一个终极版的…
new Promise((resolve,reject) => {
setTimeout(() => {
resolve('resolve传递的参数')
}, 1000);
}).then((p) => {
console.log("====第一步"+p)
return
}).then(() => {
console.log("====第二步了")
})
直接把Promse.resolve省略了。。。。。。
这里需要注意的是:如果是要调用Promse.resolve 就用 return
Promse.reject 就用 throw
Promise发送并发请求
如果有一天需要多个请求都成功之后才能进行下一步操作。那么此时可以用到promise的all(iterator)方法。
Promise.all([
new Promise((resolve,reject) => {
setTimeout(() => {
resolve({name:'hang',message:'我是第0个元素'})
}, 2000);
}),
new Promise((resolve,reject) => {
setTimeout(() => {
resolve('我是第1个元素')
}, 1000);
})
]).then(result => {
console.log(result) // 每一个promise对象
console.log(result[0]) // 第一个promise对象
console.log(result[0].name) // 输出hang
console.log(result[1]) // 第二个promise对象
})
只有当all方法里面的全部promise对象都请求完成时才会执行then方法。
axios的基本操作
Axios 是一个基于 promise 的 HTTP 库,简单的讲就是可以对网络发送get、post请求。默认get请求。
在Vue中使用axios需要先导入axios
import axios from 'axios'
发送get请求:
axios.get(
'http://127.0.0.1:5500/day0_js和ES6的补充/'
,{
params:{
// 发送get请求所需要的参数
}
}).then(res => {
console.log(res)
})
axios发送请求返回的类型是promise,所以可以用.then方法
发送post请求:
axios.post(
'http://127.0.0.1:5500/day0_js和ES6的补充/',
{
// 发送post请求时所需要的参数
name: 'Javan',
}).then(res => {
console.log(res)
})
发送并发请求
用法跟promise差不多。
axios.all([
axios({
url:'http://127.0.0.1:5500/day0_js和ES6的补充/'
}),
axios({
url:'http://127.0.0.1:5500/day10_组件化高级/'
})
])
.then(results => {
console.log(results)
console.log(results[0])
console.log(results[1])
})
配置全局信息
有些时候多个请求中都是要相同的域名或者其他的一些配置参数都相同时,可以配置全局信息,这样就不用一个一个去配置了。
// 全局配置baseURL
axios.defaults.baseURL = 'http://127.0.0.1:5500/'
// 全局配置请求响应时间
axios.defaults.timeout = 5000
axios.all([
axios({
url:'/day10_组件化高级'
}),
axios({
url:'/day0_js和ES6的补充'
})
])
.then(results => {
console.log(results)
console.log(results[0])
console.log(results[1])
})
创建axios实例(常用)
如果配置了上面的全局信息,那么接下来的任何请求中,都以这个作为自己的配置。然而在很多时候,我们会发送多个请求,而这些请求又分别需要不同的全局配置。这时就需要用到axios的实例了。每个axios实例都互不影响,而每个实例内部又可以配置该实例的全局信息。
创建实例:axio.creat({一些配合信息})
const instance1 = axios.create({
//在创建实例的时候,创建此实例的全局配置
baseURL:'http://127.0.0.1:5500',
timeout:5000
})
const instance2 = axios.create({
//在创建实例的时候,创建此实例的全局配置
baseURL:'http://127.0.0.1:5545', // 此端口号是我乱写的,为了说明例子而已
timeout:100000
})
instance1.get('/day1_Vue初体验')
.then(res => {
console.log('我是instance1实例的一个请求')
})
instance2.get('/day10_组件化高级')
.then(res => {
console.log('我是instance2实例的一个请求')
})
拦截器的使用
拦截器就是会拦截网络的请求或者响应的,此时我们可以进入我们一些想要的操作。比如请求之前要做些什么,请求之后又要做些什么,或者对响应回来的数据要做些什么处理,等等。
拦截器有requesr跟response两种,传递的参数都是两个函数(分别是拦截成功的函数和拦截失败的函数)。需要注意的是,拦截成功时记得要把接收到的参数return回去
requset拦截器的使用:实例或者axios.interceptors.request.use(成功时回调函数,失败时回调函数)
resopnse拦截器的使用:实例或者axios.interceptors.response.use(成功时回调函数,失败时回调函数)
instance.interceptors.request.use(
config => {
console.log('我是请求拦截器====成功',config)
//记得要返回config
return config
},
err => {
console.log('我是请求拦截器====失败',err)
})
instance.interceptors.response.use(
res => {
console.log('我是响应拦截器====成功',res)
//记得要返回config
return config
},
err => {
console.log('我是响应拦截器====失败',err)
})
网络请求的封装
网络请求封装的意思就是把对网络请求的操作放在一个js文件中,然后需要用时进行导入即可。
js文件中:(假设为request.js文件)
//初版
// export function request(config){
// return new Promise((resolve,reject) => {
// //1.创建实例
// const instance = axios.create({
// baseURL:'http://127.0.0.1:5500/',
// timeout:5000
// })
// instance(config)
// })
// }
// 终极版
export function request(config){
const instance = axios.create({
baseURL:'http://127.0.0.1:5500',
timeout:5000
})
return instance(config)
//因为axios实例本身返回一个promise
}
使用网络请求的文件中:
import {request} from './request.js'
request.get('/day1_Vue初体验')
.then(
res => {console.log('封装请求成功',res)})
.catch(
err => {console.log('封装请求失败',err)}
)