网络请求

@Fetch
Overview
.Fetch 是 W3C 的一种请求标准;不是第三方库,与 Vue、JQuery 无关
.是原生的 JavaScript,是 Window 的方法,属于 BOM 范畴
.下一代 Ajax 技术,基于 Promise 方式处理数据 - 返回结果是 Promise
.语法简介明了;除了IE,多数浏览器都兼容
.既可以访问远程数据,也可以访问本地数据
.需要拼接参数;需要二次封装
.以下各案例使用回调函数 callback,简化代码可以使用 asyn-await
.更多信息,请访问 Using_FetchMDN - fetchFetch_API接口调用 - fetchfetch - 请求数据
fetch(url)
console.dir(fetch);
Syntax
.拿到数据需要2次处理
.第一个 then() 返回的 Response 对象,包含了一些元数据和方法,但不直接包含请求返回的实际数据;要获取实际的 JSON 数据,需要调用 res.json() 方法将 Response 对象解析为 JSON 数据,并返回一个新的 Promise
.第二个 then() 处理解析后的 JSON 数据
.在响应的原型[[Prototype]] Response中,可以看到相关的函数,他们仍然是一个 Promise 对象,所以需要 2次 返回才能拿到结果
fetch( url, {
  method: '',
  headers: {
    'Content-Type': 'application/json'
  },
  body: ''
} )
  .then( res => res.json() )
  .then( res => {
    console.log( 'success ', res )
  } )
Configuration
method(String):HTTP 请求方法,Get 获取数据 | Post 提交数据 | Delete 删除数据 | Put 更新数据;默认为 GET
body(String):HTTP 请求的参数;POST 时使用
headers(Object):HTTP 请求头,如 content-type 的常见值为 application/json、application/x-www-form-urlencoded
如果数据是 json 格式,可以省略 header 配置项;具体还要看服务器端的适配情况
Response

根据请求的数据类型,返回的结果分别有:

res.json():得到 JSON 对象,同 JSON.parse(responseText) 一样;应用最广泛
res.text():得到文字|字符串
res.formData():得到 FormData 表单对象
res.blob():得到 Blob对象,如图片等多媒体对象
[] 获取本地/远程 .json 数据 - 在开发者视图的控制台查看获取结果
fetch('https://glpla.github.io/utils/data/rank/20240203.json')
  .then(res => res.json())
  .then(res => console.log(res))
[] text()
请求本地/远程文本文件 .txt
fetch('./tmp.txt')
  .then(res => res.text())
  .then(res => console.log(res))
请求本地/远程 .html,实现模块化;不需要写完整的html结构,只写业务结构即可;见底部版权
fetch('../../common/drill.html')
.then(res => res.text())
.then(res => {
  document.getElementById('require').innerHTML = res;
})
[] formData() - 请求表单
[] blob() - 请求图片并渲染
blob
fetch('https://glpla.github.io/utils/avatar/avatar0.png')
  .then(res => res.blob())
  .then(res => img.src = URL.createObjectURL(res))
注意
以上请求没有响应异常
fetch 请求不会抛出错误,即使是 404 或 500 错误
应根据响应状态 ok 或状态码 status 判断结果
如果要处理异常,可以使用 catch()
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://localhost:3000/clerk/2002"
ok: false
redirected: false
status: 404
statusText: "Not Found"
type: "cors"
url: "http://localhost:3000/clerk/2002"
下例中,第一个 then 中通过 throw new Error 抛出了一个错误;这个错误会被后续的 catch 块捕获。因此,从技术上讲,不需要在第一个 then 中再单独处理异常;但是,如果你希望在第一个 then 中更细致的处理异常,可以选择在这里添加额外的逻辑
fetch('/utils/data/cart.json')
.then(response => {
  if (!response.ok) {
    throw new Error('Network response was not ok ' + response.statusText);
  }
  return response.json();
})
.then(data => {
  console.log(data);
})
.catch(error => {
  console.error('There was a problem with the fetch operation:', error);
})
.finally(() => {
  console.log('Fetch operation completed.');
});
Application
.以下网络请求,基于 自建 数据服务器:express 环境下的 动态资源服务器
.也可以直接使用 线上 数据服务器 Random UserJson Placeholder
其它请求方式,需求服务器环境支持
获取数据 GET
C端

默认获取数据 - 一般是获取所有数据

fetch('https://glpla.github.io/utils/data/rank/20240203.json')
  .then(res => res.json())
  .then(res => console.log(res))

使用查询参数 query,直接在 url 后面使用 ? 拼接查询值对,使用 & 拼接多个查询参数;如获取指定数据或分页获取数据

fetch('http://127.0.0.1:3000/test?id=20240507')
  .then(res => res.json())
  .then(res => console.log(res))

使用路径参数 params

fetch('http://127.0.0.1:3000/test/20240507')
  .then(res => res.json())
  .then(res => console.log(res))
S端
router.get('/', (req, res) => {
  console.log(req.query);
  res.header('Access-Control-Allow-Origin', '*')
  res.json({
    code: 'ok',
    type: 'get',
    data: req.query.id
  })
})
router.get('/:id', (req, res) => {
  console.log('params', req.params);
  res.header('Access-Control-Allow-Origin', '*')
  res.json({
    code: 'ok',
    type: 'get',
    data: req.params.id
  })
})
增加数据 POST
url
method:POST
headers:根据数据类型设置,如 JSON 数据,默认就是 JSON,所以使用 JSON 时,也可以省略 header 的配置
body:传递 JSON 数据,需要使用JSON.stringify(data) 序列化数据;部分框架和部分服务器可以自动完成数据的序列化和解析
服务器使用 request.body 获取数据;Express 早期需要使用额外的依赖 body-parser,现在可以 直接使用 内置中间件
C端

传递JSON数据

fetch(url + '/cont', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    id: 20240508,
  })
})
  .then(res => res.json())
  .then(res => console.log(res))

传递值对,如表单数据

fetch('http://127.0.0.1:3000/test', {
  method: 'post',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: 'id=20240507'
})
  .then(res => res.json())
  .then(res => console.log(res))  
S端
router
.use(express.urlencoded({ extended: true }))  // for parsing application/x-www-form-urlencoded
.use(express.json())  // for parsing application/json when POST
      
router.post('/', (req, res) => {
  console.log('req body', req.body);
  res.json({
    code: 'ok',
    type: 'post',
    data: req.body.id
  })
})  
删除数据 DELETE
使用 路径参数,指定 method 为 DELETE
DELETE 请求通常不需要请求体,但可能需要设置 Content-Type。如果API需要,确保它被正确设置,通常为 'Content-Type': 'application/json' 或 'Content-Type': 'text/plain'
服务器端需要能够处理 DELETE 请求。有些API可能需要特定的路由或者需要在服务器端有相应的处理逻辑
默认情况下,Node + Express 没有开启 DELETE 请求;需要设置请求头;更多信息,请查看 代理 - Proxy
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
C端
fetch('http://127.0.0.1:3000/test/20240507', {
  method: 'DELETE'
})
  .then(res => res.json())
  .then(res => console.log(res))
S端
router.delete('/:id', (req, res) => {
  console.log('params', req.params);
  res.json({
    code: 'ok',
    type: 'delete',
    data: req.params.id
  })
})      
更新数据 PUT
同POST;除了指定要修改的数据外,还要以路径参数的形式指定修改谁的数据
C端
fetch('http://127.0.0.1:3000/test/123', {
  method: 'put',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    id: 20240507
  })
})
  .then(res => res.json())
  .then(res => console.log(res))
S端
router.put('/:id', (req, res) => {
  console.log('params', req.params);
  console.log('req body', req.body);
  res.json({
    code: 'ok',
    type: 'delete',
    data: req.params.id
  })
})      
推荐资源
1. 随机小狗 dog ceo
2. 随机图片 picsum photos
3. 土味情话
4. http://ajax-base-api-t.itheima.net/api
/getbooks
/addbook