fetch: 一文理解fetch如何发请求

目录

第一章 前言

1.1 注意

1.2 为什么要了解fetch

 第二章 准备工作

第三章 fetch相关知识

3.1 fetch基本请求发送(包括理解、解决fetch涉及的问题)

3.1.1 使用fetch发送get请求(使用try-catch搭配async-await)

3.1.2 了解Response对象

3.1.3 fetch 配置参数

3.2 fetch发送post请求

3.2.1 json格式发送

3.2.2 x-www-form-urlencoded格式发送

3.2.3 formData格式发送

3.3 fetch 函数封装

3.3.1 目标效果

3.1.2 封装函数

3.1.3 封装发送请求


第一章 前言

1.1 注意

该文章用到了小编最近学习技术栈给的一个服务器,是对github获取用户信息的封装,通过请求该服务器获取数据。使用的fetch发送请求,在了解该请求之前一定要对我们常用的promise方法熟练于心,小编也会对给的demo做详细的解释。

1.2 为什么要了解fetch

  • 首先先说一下我们现在最常用的axios、jquery封装的请求,它们的"根",或者说本质都是XMLHttpRequest(xhr),相关的ajax请求可以看小编的该文章

AJAX及其相关知识应用(很详细)_使用ajax需要引入什么-CSDN博客

  • 那么问题来了,如果有一天某公司说,我们的项目不使用xhr系列发送请求(比如,现在大部分还是用的axios请求的),那么我们应该怎么办,我们了解的常用的请求都是axios/jquery,这些是基于xhr的,那么我们应该怎么办,不做了吗?自己写吗?
  • 接下来,小编就要为大家介绍一个新的请求方法了,fetch! Fetch API 也是基于 Promise 设计,与xhr是不同类的请求方法采用了模块化设计,API分散于多个对象中通过数据流(Stream对象)处理数据,可以分块读取,有利于提高网站性能,对于大文件或者网速慢的场景极为有用

 第二章 准备工作

  • 开启服务器

  • 配置代理跨域

  • 理解promise

promise:一文理解promise常用的方法-CSDN博客

第三章 fetch相关知识

3.1 fetch基本请求发送(包括理解、解决fetch涉及的问题)

3.1.1 使用fetch发送get请求(使用try-catch搭配async-await)

  • 如果fetch() 只接收了一个 url字符串 参数表示默认向该网址发送 get 请求,会返回一个Promise对象
  • 如果需要设置get的参数,直接拼接到 url 地址上即可
  • 基本语法:
fetch(url)
  .then(...)
  .then(...)
  .catch(...)
  • fetch发送get请求(未优化!!-- 通过小编下面的问题一步一步得到最终优化的代码
// 1、配置好的接口地址:/api1/search/users2?q=${this.keyWord}
// 2、请求方式:get
// 3、请求参数(可选):连接到路径上,q:keyword

// 发送网络请求---使用fetch发送(未优化)
fetch(`/api1/search/users?q=${this.keyWord}`).then(
  // 一定要注意,fetch请求的第一个.then得到的并不是数据,是获取内容
  // 我们可以理解成这里能输出内容只能表示与服务器连接成功
  // response.json()该参数下的该函数表示是一个异步操作,取出所有的内容,将其转换成JSON对象
  response => {
    console.log('联系服务器成功了', response)
    return response.json()
  },
  error => {
    console.log('联系服务器失败了', error)
  }
).then(
  // 这里才是通过获取经过res.json() 处理过之后的数据—>正常通过ajax获取到的我们需要的数据
  response => { console.log('获取数据成功了', response) },
  error => { console.log('获取数据失败了', error) }
)

   -- 正常请求成功查看输出:注意我后面用第一个.then与第二个.then区分做描述

第一个.then输出:

第二个.then输出

  • 问题一:当第一个.then错误后,还会继续执行第二个.then吗?

答案:会执行,fetch请求我们知道也是使用的promise,promise的.then的链式调用,下图能验证我们的答案是正确的! 

  • 问题二:为什么第二个.then结果是数据获取成功了,输出undefined,而不是走的error失败呢?

答案:熟悉promise就知道了,首先我们看代码,第一个.then的error里直接就是console.log,没有return值,那么当没有return值时,promise就会给下一个.then返回一个undefined的值,非promise值,状态为fulfilled成功的,下一个.then接收到一个状态为fulfilled的值,肯定就走response那个函数了,输出也是undefined

  •  优化一:解决问题上述问题:

在第一个.then错误的代码里面return一个空的promise对象回调--初始化状态的promise实例(promise的解决方法),使得当错误时不会继续执行后面的.then。

    fetch(`/api1/search/users2?q=${keyword}`).then(
      response => {
        console.log('联系服务器成功了') 
        return response.json()
      },
      error => {
         console.log('炼器服务器失败了', error)
         // 返回一个空的promise回调,使得代码不再往后走了
         return new Promise(()=>{})
      }
    ).then(
      response => {
        console.log("获取数据成功", response)
      },
      error => {
        console.log("获取数据失败了", error)
      }
    )
  • 优化二:.then里面一直有 成功、失败,成功、失败的函数,promise有一个更加优化的解决方案.catch捕获错误,只要报错直接就跳到.catch,我们就不需要在每一个.then函数里面都写成功跟失败的回调函数了。
    fetch(`/api1/search/users2?q=${keyword}`).then(
      response => {
        console.log('联系服务器成功了') 
        return response.json()
      }
    ).then(
      response => {
        console.log("获取数据成功", response)
      }
    ).catch(
      (error) => {console.log("请求出错", error)}
    )
  • 优化三:(最终结果),请求的时候,针对promise对象,我们为了获取里面的值并不是都用.then获取的,儿时会使用async...await...来处理获取promise里的值,从上面两个.then我们知道应该如何使用了;然后还有注意点,await只能让我们等到成功的结果,那么失败的结果怎么拿到呢,try...catch...解决!代码如下:
  // 最终优化
  search = async () => { // async...await...搭配使用
    try { // try里面实现的是成功的代码逻辑
      const response = await fetch(`/api1/search/users2?q=${keyword}`) // 第一个请求获取到了与服务器连接成功的请求结果
      const data = await response.json() // 第二个请求拿到的才是服务器返回前端的最终结果值
      console.log(data)
    } catch (error) { // catch实现的是失败的代码逻辑
      console.log(error)
    }
  }

最终得到结果:

3.1.2 了解Response对象

不要生疏了,这个对象就是我们发送请求时第一个获取到的与服务器连接成功的请求结果,对应服务器的 HTTP 响应。

const response = await fetch(url)
console.log(response)
  • 常见属性

属性含义
response.ok返回一个布尔类型,表示请求是否成功
response.status返回一个数字,表示HTTP回应的状态码(例如:200,表示已请求成功)
response.statusText返回状态的文本信息(例如:请求成功之后,服务器返回OK)
response.url返回请求的url地址
  •  常见方法(response .json()最常用)
方法含义
response .json()得到 JSON 对象
response .text()得到文本字符串
response .blob()得到二进制 Blob 对象
response .formData()得到 FormData 表单对象
response .arrayBuffer()得到二进制 ArrayBuffer 对象

3.1.3 fetch 配置参数

fetch第一个参数是 url ,此外还可以接收第二个参数作为配置对象,只配置url默认get请求;可以自定义发出的HTTP请求post、put、patch等,其中:post、put、patch 用法类似,我们以post为例演示

fetch(url,options)
fetch(url,{ // url请求路径
    method:'请求方式,比如:post、delete、put', // 请求方法
    headers:{
        'Content-Type':'数据格式' // 请求携带的数据格式json、x-www-form-urlencoded、formdata……
    },
    body:'post请求体数据' // 参数
})

3.2 fetch发送post请求

3.2.1 json格式发送

(假设一个表带提交的接口…/add/users2)

// 测试接口(新增操作):
// 接口地址:/api/add/users2
// 请求方式:post
// 请求体参数:
//  1、姓名:name
//  2、年龄:age
//  3、出生:birthday

// post发送:json格式
async addUser() {
    let obj = {
        name: '❆VE❆',
        age: '23',
        birthday: '2000-01-01'
    }

    let response = await fetch('/api/add/users2', {
        method: 'post',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(obj)
    })

    let data = await response.json()
    console.log(data)
}

addUser()

3.2.2 x-www-form-urlencoded格式发送

async function addUser1() {
    let response = await fetch(url, {
      method: 'post',
      headers: {
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
      },
      body: 'name=❆VE❆&age=23',
    });

    let data = await response.json();
    console.log(data)
}

addUser1()

3.2.3 formData格式发送

let file = '文件的二进制流'

async function addUser2() {
    const formdata = new FormData()
    formdata.append('file', file)
    let response = await fetch(url, {
        method: 'POST',
        headers: {
          "Content-type": "multipart/form-data",
        },
        body: formdata
    })

    let data = await response.json()
    console.log(data)
}
addUser2()

3.3 fetch 函数封装

实际开发中,我们不可能对每一个请求都这么写,虽然也能实现,但是毕竟最终造成的代码冗余太多了,对于axios我们会对其进行二次封装,当然了,针对fetch我们是不是也能进行二次封装了呢!如下:

3.3.1 目标效果

不管是什么方式的请求,我们的格式都是如下,区分为两类

// 发送get请求、delete请求
request({
    method:'xxx'
    url:'xxx',
    params:{......}
})

// 发送post请求、put请求、patch请求
request({
    method:'xxx'
    url:'xxx',
    data:{......},
    headers: {......}
})

3.1.2 封装函数

async function request(obj) {
    // 解构赋值
    let { method, url, params, data, headers } = obj

    // 判断是否有params参数
    // 1、如果有params参数,则把params对象转换成 key=value&key=value的形式,并且拼接到url之后
    // 2、如果没有params参数,则不管
    if (params) {
        // 把对象转换成 key=value&key=value 的方法
        // 固定写法:new URLSearchParams(obj).toString()
        let str = new URLSearchParams(params).toString()
        // console.log(str)
        // 拼接到url上
        url += '?' + str
    }

    // 如果没有配置headers,则设置一个最常用的headers
    if(headers){
        headers = {
            'Content-Type': 'application/json'
        }
    }

    // 最终的结果
    let response 
    // 判断是否有data参数,如果有,则需要设置给body,否则不需要设置
    console.log(data)
    if (data) {
        // 如果有data参数,此时直接设置
        response = await fetch(url, {
            method: method,
            headers: headers,
            body: JSON.stringify(data)
        })
    } else {
        response = await fetch(url)
    }

    return response.json()
}

3.1.3 封装发送请求

  • get方法发送请求
data = await request({
    method: 'get',
    url: '/api/search/users2',
    params: { // 如果该get请求没有参数则不写,注意自己封装的函数逻辑,参数名别写混了
        name: '❆VE❆',
        age: '23'
    }
})
  • post等方法发送请求
data = await request({
    method: 'post',
    url: '/api/add/user',
    data: { // post请求提交参数
        name: '❆VE❆',
        age: '23'
    },
    headers: { // 如果请求头需要其他格式,配置即可,不需要封装时则会有默认的配置
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
    },
})

 

  • 28
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值