Skip to content

notion地址-day03

回顾

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的区别

axiosfetch是两个常用的发送网络请求的工具,它们有以下区别:

  1. axios可以全局配置请求拦截器和响应拦截器,方便统一处理请求和响应;fetch则没有类似的全局配置选项,需要每次手动配置请求头等信息。
  2. axios可以自动将请求体转换为JSON格式,也可以自动将响应体解析为JSON格式;fetch则需要手动处理请求体和响应体的格式转换。
  3. axios对请求超时、错误、取消等情况进行了封装处理,方便处理异常情况;fetch则没有这些封装处理。

综上,axios更加灵活、方便,也更加易于处理异常情况,因此在项目中更加常用。

promise

回调函数-JS中的异步

image.png

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