回顾
javascript
// http状态码
// 200 --> ok 请求成功
// 3xx 重定向相关的 304 ==> not modified 资源未修改/ 缓存相关
// 客户端的错误 4xx
// 400 --> 参数错了等 bad request
// 401 --> 未授权
// 403 ---> forbidden 禁止访问
// 404 --> 文件资源找不到
// 服务器的错误 5xx
// 业务状态码 ---> 响应体里面,后端定义好了,给我们的
// 有时候,即使参数错误了,后端也可能给我们一个200ok的请求成功状态码,
// 然后,在响应体中,用业务状态码来表示,这个请求有问题 {code:400; }
// ==> http状态码200ok
javascript
const api_lol = 'https://autumnfish.cn/api/lol/search' // GET 参数 q
const btn = document.querySelector('.btn')
btn.addEventListener('click', () => {
// 1. config
// axios({
// url:api_lol,
// params:{
// q:'提莫'
// }
// })
// 2. 简化模式
axios.get(`${api_lol}?q='提莫''`).then(res => {
console.log(res)
})
})
// 基地址怎么设置?
axios.defaults.baseURL = 'http://ajax-api.itheima.net'
// 测试登录接口
const api_login = '/api/login'
const btn = document.querySelector('.btn')
btn.addEventListener('click', () => {
// 1. config
// axios({
// url:api_login,
// method: 'POST',
// data:{
// username:'admin',
// password:'123456'
// }
// })
// 2. 简化模式
axios.post(api_login, {
username:'admin',
password:'12345666' // 密码故意写错
}).then(res => {
console.log(res)
}).catch(err => {
alert(err.response.data.message)
console.dir(err)
console.log(err)
})
})
Ajax
原生ajax发送请求
- readyState ==> ajax的请求状态码 0-4
- xhr.response ==> 返回的是根据Content-Type响应头自动解析的数据类型,通常是二进制数据或其他类型,如音视频等。
- xhr.responseText ==> 通常用于获取文本数据,如HTML,JSON,纯文本等。
javascript
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
// 原生发送ajax
ajax_get()
})
// 原生ajax 五步走
function ajax_get(){
// 1. 实例化xhr对象 XMLHttpRequest 内置的
const xhr = new XMLHttpRequest()
// 2. 设置请求方法和地址
xhr.open('get', 'http://ajax-api.itheima.net/api/news')
// 3. 设置请求头 ==> 可以省略 如果后端需要,就要设置,不需要,设置了也没关系,可以自定义
xhr.setRequestHeader('myHeader', 'goodHeader')
// 4. 注册回调函数
// readystatechange ==> 表示ajax请求的状态改变
// xhr.readystate ==> 从我们实例化xhr对象开始,就在变化 0-4 值, 4 表示服务器已经把数据返回给我了
xhr.addEventListener('readystatechange', function(){
if (xhr.readyState === 4){
// 什么时候是成功的请求状态 http状态?200 - 300 304 资源未修改,缓存
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(xhr.response)
} else {
console.log('请求不成功')
}
}
})
// 5. 发送请求
xhr.send()
}
// 原生发送 五部
// 1. 实例化xhr
// 2. 设置请求方法和接口地址 xhr.open(方法,地址)
// 3. 设置请求头 ==> 可以省略,看后端需要不
// 4. 注册回调函数
// 5. 发送请求
readyState 和 status 和 304
javascript
// 1. xhr.readyState ==> 表示ajax xhr当前的状态码
// 0 UNSENT 代理被创建,但尚未调用 open() 方法。
// 1 OPENED open() 方法已经被调用。但是send方法还没调用
// 2 HEADERS_RECEIVED 请求已接收,send() 方法已经被调用,正在处理中(通常可以从响应头中获取部分内容)
// 3 LOADING 请求处理中,下载中;responseText 属性已经包含部分数据。
// 4 DONE 请求已完成,下载操作已完成。 XHR对象已经接收到完整的响应数据
// 2. xhr.status ==> 它实际上就是http状态码
// 3. 304 资源未修改
// 协商缓存, 两个请求头:一个是 If-Modified-since / If-None-match
// ==> 浏览器在发送请求的时候,附加一个请求头,去问服务器,资源有没有改动,
// ==> 服务器,看到了这个请求头, 就会去它自己的本地查看一下是否修改,如果没有修改,返回304
// ==> 告诉浏览器,资源没有修改哟,你可以直接用上次请求的那个资源。
readyState状态码
javascript
// 1. 实例化xhr
const xhr = new XMLHttpRequest()
console.log(xhr.readyState) // 0
// 2. 设置请求方法和地址
xhr.open('get', 'http://ajax-api.itheima.net/api/news')
console.log(xhr.readyState) // 1
// 3. 请求头,忽略,可以不设置
// 4. 注册回调函数
xhr.addEventListener('readystatechange', function(){
console.log(xhr.readyState) // 2 3 4
})
// // 5. 发送请求
xhr.send()
// xhr.readyState 表示的是ajax经历的几种状态,它的一个执行过程,
// ==> 可以理解为ajax的运行步骤,表示xhr对象当前的状态值
// xhr.status http状态码,是服务器返回给我们的,请求成功与否等状态
// ===> 体现的是服务器对请求的反馈
xhr对象的load事件和readyStateChange
javascript
// load 表示的是 readyStateChange为 4 ===> 即为load事件, 一次ajax请求,只会触发一次
// readystatechange ==> 一次ajax请求,会多次触发
// 原生ajax的写法,可以写成以下两种形式
// 1. 创建xhr对象
const xhr = new XMLHttpRequest()
// 2. 设置请求方法和地址
xhr.open('get', URL)
// 3. 请求头
// 4. 注册回调函数
xhr.addEventListener('load', function(){
// 就不用判断状态为4
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(xhr.response)// ==> 可以
console.log(xhr.responseText) // ==> 可以
// xhr.response 是根据响应头里面的 content-type自动解析的,一般是二进制的数据,音视频
// xhr.responseText 一般是文本数据,比如html,json,纯文本。
}else{
console.log('请求不成功')
}
})
// 5. 发送请求
xhr.send()
// 另一种 reaystatechange 参考最开始的那种情况
const xhr = new XMLHttpRequest()
// 2. 设置请求方法和地址
xhr.open('get', 'http://ajax-api.itheima.net/api/news')
// 3. 设置请求头 ==> 可以省略 如果后端需要,就要设置,不需要,设置了也没关系,可以自定义
xhr.setRequestHeader('myHeader', 'goodHeader')
xhr.setRequestHeader('otherHeader', 'dogHead')
// 4. 注册回调函数
// readystatechange ==> 表示ajax请求的状态改变
// xhr.readystate ==> 从我们实例化xhr对象开始,就在变化 0-4 值, 4 表示服务器已经把数据返回给我了
xhr.addEventListener('readystatechange', function(){
if (xhr.readyState === 4){
// 什么时候是成功的请求状态 http状态?200 - 300 304 资源未修改,缓存
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(xhr.response)
} else {
console.log('请求不成功')
}
}
})
get请求传参-qs
javascript
<button>点击发送ajax</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
// 原生发送ajax
ajax_get_qs()
})
// 原生ajax 五步走
function ajax_get_qs(){
// 1. 实例化xhr对象 XMLHttpRequest 内置的
const xhr = new XMLHttpRequest()
// 2. 设置请求方法和地址
// 原生的ajax,没有params,所以,直接拼接到url上,
// ===> 查询字符串 queryString url?key=val&key2=val2
xhr.open('get', 'http://ajax-api.itheima.net/api/robot?spoken=你好,你吃饱了没?')
// 3. 设置请求头 ==> 可以省略 如果后端需要,就要设置,不需要,设置了也没关系,可以自定义
// xhr.setRequestHeader('myHeader', 'goodHeader')
// xhr.setRequestHeader('otherHeader', 'dogHead')
// 4. 注册回调函数
// readystatechange ==> 表示ajax请求的状态改变
// xhr.readystate ==> 从我们实例化xhr对象开始,就在变化 0-4 值, 4 表示服务器已经把数据返回给我了
xhr.addEventListener('readystatechange', function(){
if (xhr.readyState !==4) return
// 什么时候是成功的请求状态 http状态?200 - 300 304 资源未修改,缓存
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(xhr.response)
} else {
console.log('请求不成功')
}
})
// 5. 发送请求
xhr.send()
}
post请求传参-设置请求头
javascript
const btn = document.querySelector('button')
const api = 'http://ajax-api.itheima.net/api/data'
// 表单的形式 application/x-www-form-urlencoded'
const data = 'username=admin&password=123456'
btn.addEventListener('click', () => {
// 原生发送ajax
ajax_post()
})
// 原生ajax 五步走
function ajax_post(){
// 1. 实例化xhr对象 XMLHttpRequest 内置的
const xhr = new XMLHttpRequest()
// 2. 设置请求方法和地址
xhr.open('POST', api)
// 3. 设置请求头 ==> 可以省略 如果后端需要,就要设置,不需要,设置了也没关系,可以自定义
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
// 4. 注册回调函数
// readystatechange ==> 表示ajax请求的状态改变
// xhr.readystate ==> 从我们实例化xhr对象开始,就在变化 0-4 值, 4 表示服务器已经把数据返回给我了
xhr.addEventListener('readystatechange', function(){
if (xhr.readyState !==4) return
// 什么时候是成功的请求状态 http状态?200 - 300 304 资源未修改,缓存
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(xhr.response)
} else {
console.log('请求不成功')
}
})
// 5. 发送请求
// 如果是get请求,send可以为空,或者null
// post请求,在这里写参数
xhr.send(data)
}
// 注意:如果是post请求,原生ajax,需要设置一个请求头,告诉后端,我发送的数据是什么格式的,
// 后端接口文档中写了需要什么样格式的数据!,我们照着设置就好了
post请求-json格式
javascript
<button>点击发送ajax-post-json</button>
const btn = document.querySelector('button')
const api = 'http://ajax-api.itheima.net/api/login'
// 表单的形式 application/x-www-form-urlencoded'
const data = {username:'admin', password:'123456'}
btn.addEventListener('click', () => {
// 原生发送ajax
ajax_post_json(api, data)
})
// 原生ajax 五步走
function ajax_post_json(url, data){
// 1. 实例化xhr对象 XMLHttpRequest 内置的
const xhr = new XMLHttpRequest()
// 2. 设置请求方法和地址
xhr.open('POST', url)
// 3. 设置请求头 ==> 可以省略 如果后端需要,就要设置,不需要,设置了也没关系,可以自定义
xhr.setRequestHeader('content-type', 'application/json')
// 4. 注册回调函数
// readystatechange ==> 表示ajax请求的状态改变
// xhr.readystate ==> 从我们实例化xhr对象开始,就在变化 0-4 值, 4 表示服务器已经把数据返回给我了
xhr.addEventListener('readystatechange', function(){
if (xhr.readyState !==4) return
// 什么时候是成功的请求状态 http状态?200 - 300 304 资源未修改,缓存
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(JSON.parse(xhr.response))
} else {
console.log('请求不成功')
}
})
// 5. 发送请求
// 如果是get请求,send可以为空,或者null
// post请求,在这里写参数
xhr.send(JSON.stringify(data))
}
fetch
fetch-get
- fetch API 并没有提供进度事件,如果需要检测请求的进度,可以使用 XMLHttpRequest 对象。
javascript
// fetch 是一个现代的API,是基于XMLHttpRequest的嘛?不是的
// fetch 是基于promise实现的, promise 承诺
const api = 'http://ajax-api.itheima.net/api/robot?spoken=我很好,哈哈哈?'
fetch(api).then(res => res.json()).then(res => {
// 请求成功的响应
console.log(res)
}).catch(err => {
// 如果有错误,这里处理
console.log(err)
})
fetch发送post请求
javascript
<button>fetch发送请求</button>
<script>
const api_login = 'http://ajax-api.itheima.net/api/login'
const data = {username:'admin', password:'123456'}
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
fetch(api_login, {
method:'post',
// 1. 要注意设置headers请求头
headers:{
'content-type': 'application/json'
},
// 2. 参数是写到body这个属性上的
body: JSON.stringify(data)
}).then(res => res.json()).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
})
</script>
fetch发送post请求,上传图片
javascript
input{
display: none;
}
button{
background-color: skyblue;
border-radius: 8px;
height: 40px;
line-height: 40px;
width: 200px;
border: transparent;
}
javascript
<input type="file" accept="image/*">
<button>选择文件</button>
<img src="" alt="">
<script>
const btn = document.querySelector('button')
const ipt = document.querySelector('input')
const img = document.querySelector('img')
btn.addEventListener('click', () => {
ipt.click()
})
const api_avatar = 'http://ajax-api.itheima.net/api/file'
ipt.addEventListener('change', () =>{
// 怎么获取刚选中的img
// const img = ipt.files[0]
// console.log(img)
// 这个img要放到哪里呢?FormData那个实例上
const formdata = new FormData()
formdata.append('avatar', ipt.files[0])
fetch(api_avatar, {
method:'POST',
// headers:{
// 'Content-Type': 'image/png' ==> 和后端约定好要不要请求头
// },
body:formdata
}).then(res => res.json()).then(res => {
console.log(res)
img.src = res.data.url
})
})
</script>
fetch和axios的区别
axios
和fetch
是两个常用的发送网络请求的工具,它们有以下区别:
axios
可以全局配置请求拦截器和响应拦截器,方便统一处理请求和响应;fetch
则没有类似的全局配置选项,需要每次手动配置请求头等信息。axios
可以自动将请求体转换为JSON
格式,也可以自动将响应体解析为JSON
格式;fetch
则需要手动处理请求体和响应体的格式转换。axios
对请求超时、错误、取消等情况进行了封装处理,方便处理异常情况;fetch
则没有这些封装处理。
综上,axios
更加灵活、方便,也更加易于处理异常情况,因此在项目中更加常用。
promise
回调函数-JS中的异步
javascript
// 回调函数: 把一个函数作为参数传入到另外一个函数中,那么这个函数就叫做回调函数。
// 定时器 防抖节流,事件绑定
// ajax发送请求,axios发送请求(基于xhr).then(res => {}) .catch(err => {})
// 1. ajax
// 2. setTimeout / setInterval
// 3. 事件绑定 点击事件,页面加载事件
// 回调函数,有同步执行的,也有异步执行的,但大多数都是异步执行的。
// 同步:一件一件依次执行
// 异步:同时,不会阻塞后面代码的执行。回头再调用,当满足触发条件的时候,才回过头来调用执行。
// const arr = [1, 2, 3]
// // arr.forEach(cbFn)
// // 同步的回调 不需要等待的
// arr.forEach(function(el){
// console.log(el)
// })
// console.log(1)
// setTimeout是异步的,不会阻塞代码的运行,
// setTimeout(() => {
// console.log(2)
// }, 1000);
// setTimeout(() => {
// console.log(4)
// }, 0);
// console.log(3)
// 1 3 2 4
// 1 3 4 2
// 先执行同步的代码,执行完之后,再去看异步的
// 需求:等1秒输出 红色,一定是红色输出之后, 再过两秒输出 黄色, 再过3秒 输出绿色 ?
// 异步函数 不会立即执行,那么这么嵌套的话,阅读性不好
setTimeout(() => {
console.log('红色')
setTimeout(() => {
console.log('黄色')
setTimeout(() => {
console.log('绿色')
setTimeout(() => {
console.log('紫色')
}, 4000);
}, 3000);
}, 2000);
},4); // 这个延迟时间是不准确的,它一定会等待同步代码执行完之后,才执行。
// setTimeout是异步的,怎么理解?因为当js代码运行到setTimeout这个位置的时候,
// setTimeout会开启一个定时器,等待回调函数的执行。
const arr = new Array(10000).fill(0)
arr.forEach(el => console.log(el))
// 但是异步的它,不会阻塞它后面代码的运行。在等待的这个过程中,我还可以执行后面的代码。
// console.log(11231)
// 异步回调函数,可能会造成回调地狱的问题!!!
// 当我们需要等待一个回调完成再执行下一个回调的时候,如果依次套娃,回调地狱
// promise承诺,promise设计之初,就是为了解决回调地狱的问题滴~~
// btn.addEvenListener('click', (el) => {
// cb()
// })
promise承诺!!
javascript
// 1. 创建 并传入回调函数
const p = new Promise((resolve,reject)=>{
// 内部一般封装异步的操作
// 成功执行 resolve
// 失败执行 reject
})
// 2. 使用
p.then(res=>{}) // resolve的值
.catch(err=>{}) // reject的值
javascript
// 链式操作。就是可以点完了继续点
// const arr = [1, 2, 3]
// arr.map(el => el * 2).map(el => el * 3).filter(el => el >= 3).map()
// 为什么上面可以一直点下去?因为调用每个map或者filter方法之后,
// 返回值又是一个数组,所以可以链式操作
// Q: Promise也是可以链式操作的?--->
/* ==================== promise ===================== */
// Promise 承诺 保证 许诺
// 步骤
// 1. 许下承诺,想好诺言成功和失败的情况。
// ---> 如果明年月入百万,捐66所希望小学。如果失败了呢,下次一定。
// new Promise()
// 成功的情况, resolve(成功的结果)
// 失败了呢 reject(reson失败的理由,原因)
// 2. 获取诺言的一个结果
// promise.then(res => {}).catch(err => {})
// const p = new Promise(cbFn)
// resolve / reject 是函数
const promise = new Promise(function(resolve, reject){
setTimeout(() => {
if (Math.random() > 0.5){
resolve('成功了,欧耶')
} else {
reject('哎呀,失败了,不小心,下次一定')
}
}, 2000);
})
// promise这个对象,一开始是pendding状态,等待
promise.then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
promise的三种状态
javascript
// promsise对象的三种状态
// 1. pending 等待状态 new Promise
// 2. fulfilled 已成功
// 3. rejected 已失败
// 1. 对象的状态不受外界影响。 resolve ==> 成功, reject失败了
// 2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果
const p = new Promise((resolve, reject) => {
// 一般处理一些异步操作
resolve('success1')
reject('error')
resolve()
})
p.then(res => {
console.log(`then : ${res}` )
}).catch(err => {
console.log(`catch : ${err}`)
})
// Q: 最后log什么? then:success1 状态一旦确定,就不会再变了
then的回调的执行时机
javascript
const p = new Promise((resolve, reject) => {
// 1. new Promise的时候,这里面的代码是同步的,立即执行,一个一个挨着执行
console.log(1)
resolve() // ==> 它会执行,只是不会立马进入then,
// resolve和 reject 他们不会阻止代码的运行,只是改变了状态
console.log(2)
})
// .then()的回调函数,是异步的,要等待同步任务执行完之后才会执行
p.then((res) => {
console.log(res)
console.log(3)
})
console.log(4)
// 1243 ==> 脑瓜一开
// 1. new Promise的时候,这里面的代码是同步的,同步执行,一个一个挨着执行
// 2. 当所有的同步代码执行完之后,再去执行then的回调
// then的回调要等同步任务执行完才会执行。 then是异步的
promise链式调用
javascript
// 链式操作。就是可以点完了继续点
// const arr = [1, 2, 3]
// arr.map(el => el * 2).map(el => el * 3).filter(el => el >= 3).map(el => el *3)
// 为什么上面可以一直点下去?因为调用每个map或者filter方法之后,返回值又是一个数组,所以可以链式操作
// Q: Promise也是可以链式操作的?--->
// 每一个promise调用.then()或者.catch之后,又返回一个promsie对象
const p = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('1')
}, 1000)
})
console.log(p)
p.then(res => {
console.log(`res:${res}`)
// 过两秒之后,打印2
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('2')
}, 2000)
})
})
.then(res => {
console.log(`res:${res}`)
// 过三秒之后,打印,3
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('3')
}, 3000)
})
})
.then(res => {
console.log(res)
})
// 每一个点then之后,又返回了一个promise对象,
// 然后呢,这个promise对象又有.then()方法
抽离promise
javascript
// 抽离一个延迟执行的函数出来
function delay(s){
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(`延迟了${s}秒执行`)
}, s * 1000)
})
}
console.log(delay(1))
delay(1).then(res => {
console.log(res)
return delay(2)
}).then(res => {
console.log(res)
return delay(3)
}).then(res => {
console.log(res)
})
sleep函数
// 延迟某段时间执行某段代码
**const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))**
javascript
const resolve = ()=>{
console.log(1)
}
setTimeout(() => {
resolve()
}, 1000);
setTimeout(resolve, 1000)
function delay(s){
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve()
}, s * 1000)
})
}
// console.log(delay(1))
const sleep = ms => {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, ms)
})
}
// 延迟某段时间执行某段代码
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
// console.log(sleep(1000))
sleep(1000).then(() => {
console.log(1)
return sleep(2000)
}).then(() => {
console.log(2)
})
// ==> 用异步的方法去实现了同步的功能。
封装简化版axios
javascript
// axios 基于 xhr 和 promise封装的
function myAxios(){
return new Promise((resolve, reject) => {
// 立马执行
// 发送请求
// 1. 实例化xhr
const xhr = new XMLHttpRequest()
// 2. 设置方法和接口
xhr.open('get', 'http://ajax-api.itheima.net/api/news')
// 3. 请求头
// xhr.setRequestHeader(key, val)
// 4. 注册回调函数
xhr.addEventListener('load', () => {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log()
resolve(JSON.parse(xhr.response))
} else {
reject('请求失败')
}
})
// 5. 发送请求
xhr.send()
})
}
myAxios().then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
next-Promise静态
axios封装参数提取,GET请求
javascript
function myAxios(config){
return new Promise((resolve, reject) => {
// 解构 ==> 可以设置默认值
const {url, method = 'get'} = config
// 原生ajax 五步走
// 1. 实例化xhr
const xhr = new XMLHttpRequest()
// 2. 设置方法和接口
xhr.open(method, url)
// 3. 请求头
// xhr.setRequestHeader(key, val)
// 4. 注册回调函数
xhr.addEventListener('load', () => {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log()
resolve(JSON.parse(xhr.response))
} else {
reject('请求失败')
}
})
// 5. 发送请求
xhr.send()
})
}
const api = 'http://ajax-api.itheima.net/api/news'
myAxios({
url:api,
// method:'get'
}).then(res => {
console.log(res)
})
ajax-添加post
javascript
<h2>post传递JSON数据给后端</h2>
<div class="wrap">
<button class="get">获取图书</button>
<button class="add">新增图书</button>
<button class="edit">修改图书</button>
<button class="delete">删除图书</button>
</div>
<script>
/*
参数是一个对象config
url
method
data:{} 通过请求体传递的数据写在data属性里面
*/
function myAxios(config){
return new Promise((resolve, reject) => {
const {url, method = 'get', data} = config
// 原生ajax 五步走
// 1. 实例化xhr
const xhr = new XMLHttpRequest()
// 2. 设置方法和接口
xhr.open(method, url)
// 3. 请求头
xhr.setRequestHeader('content-type', 'application/json')
// 4. 注册回调函数
xhr.addEventListener('load', () => {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log()
resolve(JSON.parse(xhr.response))
} else {
reject('请求失败')
}
})
// 5. 发送请求
xhr.send(JSON.stringify(data))
})
}
// apifox:
// https://apifox.com/apidoc/shared-fa9274ac-362e-4905-806b-6135df6aa90e/api-25018003
// GET
const api_get = 'http://ajax-api.itheima.net/api/books'
// POST JSON格式 bookname/author/publisher
const api_add = 'http://ajax-api.itheima.net/api/books'
// 修改图书 PUT JSON格式 id
const api_edit = 'http://ajax-api.itheima.net/api/books/{id}'
// 删除图书 DELETE id
const api_del = 'http://ajax-api.itheima.net/api/books/{id}'
// const btn_get = document.querySelector('.get')
// const btn_add = document.querySelector('.add')
// const btn_edit = document.querySelector('.edit')
// const btn_del = document.querySelector('.delete')
// 事件委托绑定事件
const box = document.querySelector('.wrap')
box.addEventListener('click', (e) => {
if(e.target.className === 'get'){
// console.log(111)
myAxios({
url:api_get,
}).then(res => {
console.log(res)
})
}
})
</script>
完整代码
javascript
function myAxios(config){
return new Promise((resolve, reject) => {
const {url, method = 'get', data} = config
// 原生ajax 五步走
// 1. 实例化xhr
const xhr = new XMLHttpRequest()
// 2. 设置方法和接口
xhr.open(method, url)
// 3. 请求头
xhr.setRequestHeader('content-type', 'application/json')
// 4. 注册回调函数
xhr.addEventListener('load', () => {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(1111)
resolve(JSON.parse(xhr.response))
} else {
reject('请求失败')
}
})
// 5. 发送请求
xhr.send(JSON.stringify(data))
})
}
// apifox:
// https://apifox.com/apidoc/shared-fa9274ac-362e-4905-806b-6135df6aa90e/api-25018003
// GET 获取图书
const api_get = 'http://ajax-api.itheima.net/api/books'
// 新增图书
// POST JSON格式 bookname/author/publisher
const api_add = 'http://ajax-api.itheima.net/api/books'
// 修改图书 PUT JSON格式 id
const api_edit = 'http://ajax-api.itheima.net/api/books'
// 删除图书 DELETE id
const api_del = 'http://ajax-api.itheima.net/api/books'
// const btn_get = document.querySelector('.get')
// const btn_add = document.querySelector('.add')
// const btn_edit = document.querySelector('.edit')
// const btn_del = document.querySelector('.delete')
// 事件委托绑定事件
const box = document.querySelector('.wrap')
box.addEventListener('click', (e) => {
if(e.target.className === 'get'){
// console.log(111)
myAxios({
url:api_get,
}).then(res => {
console.log(res)
})
}
if(e.target.className === 'add'){
myAxios({
url:api_add,
method:'post',
data:{
bookname:'新增的',
author:'xx',
publisher:'hh'
}
}).then(res => {
console.log(res)
})
}
if (e.target.className === 'edit'){
myAxios({
url:`${api_edit}/325`,
method:'put',
data:{
bookname:'新增的修改',
author:'xx',
publisher:'hh'
}
}).then(res => {
console.log(res)
})
}
if (e.target.className === 'delete'){
myAxios({
url:`${api_del}/318`,
method:'delete',
}).then(res => {
console.log(res)
// alert('删除成功')
}).catch(err => {
console.log(err)
})
}
})
promise.then() 的返回值
javascript
const p = new Promise((resolve, reject) => {
// 一些异步代码
resolve('success')
})
// console.log(p)
// 1. promise.then() 返回一个promise对象
const res1 = p.then(res => {
console.log(res)
})
res1.then(res => {
console.log(res)
})
// console.log(res)
// 2. 如果p.then中回调函数,返回了一个非promise的值,
// 则新的promise的将使用这个值作为成功的结果
const res2 = p.then(res => {
console.log(res)
return 'second success'
})
// console.log(res)
// 3. 如果回调函数本身返回了一个promise对象,则then方法调用后返回的新promise
// 与该promise对象采用相同的成功结果或失败原因
const res3 = p.then(res => {
console.log(res)
return new Promise((resolve,reject) => {reject(1)})
})
// console.log(res)
===> 一句话总结 p.then() 返回的是一个promise对象,
// 1. then的回调中没有return ,那么promise成功的结果为undefined
// 2. then中return了一个非promise对象,新promise以该值作为成功的结果
// 3. then中return了一个promise对象,新promise 成功或失败与它相同
promsie.then() 第二个参数
javascript
const p = new Promise((resolve,reject) => {
setTimeout(()=>{
if(Math.random() > 0.5){
resolve('success')
} else {
reject('failed')
}
}, 1000)
})
// catch的方式用的更多一些推荐使用
p.then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
// promise.then() 可以接收两个函数作为参数,
// 第一个函数是promise状态为fulfilled时调用
// 第二个回调函数是promise对象为reject时调用
p.then((res)=>{
console.log(res)
}, (err)=>{
console.log(err)
})
Promise.resolve()
javascript
// Promsie.resolve() promise的静态方法
// ==> 调用这个方法,返回的就是一个promsie对象
// const p = Promise.resolve(1)
// const p = Promise.resolve('123')
// 1. 如果不传参数 => 返回的就是一个成功态的promise对象,结果为undefined
const p = Promise.resolve()
console.log(p)
// 2. 如果传入的value是一个普通的值或者对象,返回一个新的promise对象,
// 并且它的状态是已完成/成功的, 值就是传入的这个值
const p = Promise.resolve({name:'果果'})
console.log(p)
p.then(res => {
console.log(res)
})
Promise.resolve(1)
// ==> 等价于
new Promise(resolve => resolve(1))
// 3. 如果传入的value就是一个promise对象
// Promise.resolve将原封不动的,返回这个promise
const p2 = new Promise((resolve, reject) => {
reject('失败了')
})
const p3 = Promise.resolve(p2)
console.log(p3)
Promise.reject()
javascript
// Promise.reject() 返回一个新的promise对象,并且状态是失败,结果就是传入的参数
const p = Promise.reject('出错了')
console.log(p)
// 等同于
// const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, err => {
console.log(err)
})
Promise.reject('出错了').catch(err => {
console.log(err)
})
Promise.all()
javascript
// Promsie.all() 静态方法
// 1. Promise.all接收一个promise数组作为参数,返回一个新的promise对象。
// const p = Promise.all([p1, p2, p3])
// 最后p的状态,由p1,p2,p3决定
// 分两种情况
// 2.1 当p1,p2,p3都为fulfilled状态时,p的状态才会变成fulfilled(成功态、完成态)
// p1,p2,p3的返回值,会挨个(按顺序)的组成一个新的数组,作为p的结果
// 2.2
// 只要p1, p2, p3 有一个被rejected了,失败了,p的状态就会变成rejected,
// 第一个被rejected的promise的值(失败的原因),会作为p的结果
// ==> p.catch(err => console.log(err))
const p1 = Promise.resolve(111)
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(222)
}, 2000);
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(333)
}, 3000);
})
const p4 = Promise.reject('失败了4')
const p5 = Promise.reject('失败了5')
// 1. 所有的promise都成功了
const p = Promise.all([p1, p2, p3])
p.then(res => {
console.log(res)
})
console.log(p)
// 2. 有一个promise失败了
const p21 = Promise.all([p1, p2, p4])
console.log(p11)
p11.then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
// 3. 有两个promise失败了, 第一个失败的值会作为promise.all的结果
const p22 = Promise.all([p1, p4, p5])
console.log(p22)
p22.then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
Promise.race()
javascript
// Promise.race() 接收一个promise数组
// 只要p1, p2, p3之中 有一个实例率先改变状态,p的状态就跟着改变
// race返回一个promise,它可以是完成态(成功态fulfilled),也可以是失败(rejected)
// race 竞赛,只认第一名
// const sleep = (ms) => {
// return new Promise((resolve) =>{
// setTimeout(() => {
// resolve(ms)
// }, ms);
// })
// }
const sleep1 = s => new Promise(resolve => setTimeout(resolve, s * 1000))
// 上面这个返回值是undefined,1s后 => 成功态
const sleep2 = s => new Promise(resolve => setTimeout(resolve(s), s * 1000))
// 上面这个resolve(s) 立即执行了 , 立即得到1000结果
const sleep = s => new Promise(resolve => setTimeout(() => { resolve(s) }, s * 1000))
// sleep(1000).then(res => {
// console.log(res)
// console.log(222)
// })
// sleep(1000).then(res => {
// console.log(res)
// })
const p1 = sleep(1)
const p2 = sleep(6)
const p3 = sleep(5)
const p4 = Promise.reject('error')
const p = Promise.race([p1, p2, p3, p4])
console.log(p)
p.then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
Promise.all和Promise.race
javascript
const api_books = 'http://ajax-api.itheima.net/api/books'
const api_news = 'http://ajax-api.itheima.net/api/news'
const api_robot = 'http://ajax-api.itheima.net/api/robot?spoken=你不好'
// Promise.all()
const fetch_book = fetch(api_books).then(res => res.json())
// console.log(fetch_book)
const fetch_news = fetch(api_news).then(res => res.json())
// console.log(fetch_news)
const fetch_robot = fetch(api_robot).then(res => res.json())
// console.log(fetch_robot)
// 所有的请求都成功了,返回给P
const p = Promise.all([fetch_book,fetch_news,fetch_robot])
console.log(p)
// Promise.race()
// 谁最快,最快的那个拿过来
const p2 = Promise.race([fetch_book,fetch_news,fetch_robot])
console.log(p2)
// all获取所有,race获取第一个
Promise.allSettled
想知道每一个promise的结果时,可以使用promise.allSettled
javascript
// 接收一个Promise数组,在所有promise对象都已经fulfilled或rejected后
// 返回一个返回每个promise结果的对象数组.
// 每个对象有三个属性
// status => promsie的状态: fulfilled / rejected
// value =>成功的结果,如果rejected,undfined
// reason =>失败的原因,如果fulfilled,undefined
const sleep = s => new Promise(resolve => setTimeout(() => { resolve(s) }, s * 1000))
const promises = [
Promise.resolve(1),
Promise.reject('error'),
Promise.resolve(3),
sleep(5)
]
Promise.allSettled(promises).then(res => {
// 等结果--> 有了结果,才执行.then的回调
console.log(res)
})