当前位置: 首页 > news >正文

快速搭建服务器,fetch请求从服务器获取数据

 1.strapi

        首先strapi是一个api管理系统,可以让我们直接用网页的形式去定义自己的api,包括设置模型和权限等功能。

        首先直接在项目目录里面安装库。npx create-strapi@latest server --quickstart这样就可以直接在项目目录创建一个连接数据库的服务器了。不用我们去书写代码,直接在网页版数据库添加表以及表中的数据就可以自动生成api让我们去访问请求了。

        

        就是这种,我们网页形式创建表,添加权限,自动生成api。这样我们就可以在前端发送请求去获取数据了。值得一提的是记得npm的版本以及node.js版本会有限制。

        可以装一个nvm管理自己开发项目用的node。

        我是mac系统所以用brew安装nvm brem install nvm,然后创建nvm工作目录 mkdir ~/.nvm

然后配置终端环境变量,nano ~/.zshrc 然后文件内容

Maestro CLI
export PATH="$HOME/.maestro/bin:$PATH"OpenJDK 17
export PATH="/opt/homebrew/opt/openjdk@17/bin:$PATH"nvm 配置(Homebrew 路径,Apple M 芯片)
export NVM_DIR="$HOME/.nvm"
[ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh"
[ -s "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm"

        然后control x退出 按y 再按回车保存退出成功。在执行立即生效命令 source ~/.zshrc这样nvm就配置好了。我们用nvm install 22装上 22版本的node.js然后nvm use 22就可以创建strapi项目了。

2.fetch 

         上面网页可以看到我们路由是/api/students,那么我们就可以尝试去用fetch(浏览器自带的发送请求的api,是浏览器提供的全局函数,返回的一个promise)所以可以用链式调用.then.catch因为promise有状态,请求成功自动执行.then失败会自动调用.catch而且参数就是返回的promise实例对象。

import React, { useEffect } from 'react'export default function App() {const [person, setPerson] = React.useState([])const [show, setShow] = React.useState(false)/*从接口http://localhost:1337/api/students中加载数据组件一渲染就向服务器发送请求加载数据组件初始化时候发送请求来加载数据*/useEffect(() => {//说明数据开始加载了setShow(true)//发送请求//fetch()用来向服务器发送请求加载数据,Ajax的升级版//需要两个参数 1.请求地址2.请求信息//promise两个特点 成功和失败两个回调函数.then成功时候调用 .catch失败时调用fetch('http://localhost:1337/api/students/').then((res) => {//response表示响应信息// console.log(res);return res.json();//该方法可以将响应的json直接转换为js对象}).then((data) => {console.log(data.data);// 将加载到的数据设置进state中setPerson(data.data)setShow(false)}).catch(() => { })}, [])return (<div>{show ? (<p>正在加载中...</p>) : (person.map((item) => (<div key={item.id}>{item.name} --- {item.gender} --- {item.age}</div>)))}</div>)
}

        这里我们没有写fetch发送请求的类型,所以是get。这里展示数据成功,说明访问成功之后把数据返回来了,但是第一次是json类型

        

        我们需要去转化成对象。比如这里再次使用.then是因为前面的.then把json转化为js对象。然后return返回的也是一个promise实例对象。所以可以.then,报错.catch捕捉。 

        

        这里转化的js对象有两个属性一个是data,一个是meta(不认识),但是我们展开确定我们需要的是data里面的对象 

        所以用setState去存住返回来的数据就可以去展示到页面上面了。就实现了第一次用fetch请求api响应数据展示的过程了。

        但是我们要知道还有一个.catch我们没有去写,比如我们去掉路由students中的s,

 

 

        返回404但是问题是map也就是map方法错了所以请求整个过程还是执行了?这很明显不对。但是我们看到ok变为false,那么我们就可以去截断这个请求过程。而且statusText都变了。

        

        对比我们就知道如果错了,ok和statueText会改变,那就对这些进行判断。

         

        比如这里,这样如果错误就不会再执行请求后面的代码了。因为只有成功才会返回promise实例对象,才可以调用后面的.then,而且.catch没有内容所以什么都没有。

import React, { useEffect } from 'react'export default function App() {const [person, setPerson] = React.useState([])const [show, setShow] = React.useState(false)const [err, setError] = React.useState(null)/*从接口http://localhost:1337/api/students中加载数据组件一渲染就向服务器发送请求加载数据组件初始化时候发送请求来加载数据*/useEffect(() => {//说明数据开始加载了setShow(true)//发送请求//fetch()用来向服务器发送请求加载数据,Ajax的升级版//需要两个参数 1.请求地址2.请求信息//promise两个特点 成功和失败两个回调函数.then成功时候调用 .satch失败时调用fetch('http://localhost:1337/api/students/').then((res) => {//判断是否正常返回响应信息if (res.ok) {console.log(res);return res.json()}//代码运行到这里 说明没有加载到数据// setShow(false)//抛出一个错误throw new Error('数据加载失败')// response表示响应信息// console.log(res);// return res.json();//该方法可以将响应的json直接转换为js对象}).then((data) => {// console.log(data);// 将加载到的数据设置进state中setPerson(data.data)setShow(false)}).catch((e) => {//catch中的回调函数用来统一处理错误//catch执行说明上面代码出错setShow(false)// console.log(e);console.log('e', e)setError(e)})}, [])return (<div>{show && <p>加载中</p>}{err && <p>出错了:{err.message}</p>}{!show && !err && person.map((item) => (<div key={item.id}>{item.name} --- {item.gender} --- {item.age}</div>))}</div>)
}

        当报错的时候用throw new Error(‘’)扔出一个err,然后.catch就可以捕捉到。这样就完成了整个请求的逻辑,首先要有一个state接收响应数据,还要有一个state去控制请求发送后如果没有即使响应展示的内容,还需要一个state去控制页面如果报错了展示错误信息,

3.async await语法糖

import React, { useEffect } from 'react'export default function App() {const [person, setPerson] = React.useState([])const [show, setShow] = React.useState(false)const [err, setError] = React.useState(null)useEffect(() => {const fetData = async () => {try {setShow(true)setError(null)const res = await fetch('http://localhost:1337/api/students')if (res.ok) {const data = await res.json()setPerson(data.data)} else {throw new Error('数据加载失败!')}} catch (e) {setError(e)} finally {setShow(false)}}fetData()}, [])return (<div>{show && <p>加载中</p>}{err && <p>出错了:{err.message}</p>}{!show && !err && person.map((item) => (<div key={item.id}>{item.name} --- {item.gender} --- {item.age}</div>))}</div>)
}

         

        最开始我们使用 fetch 是通过连续调用 .then 来一步步获取 response 和 json 数据,因为 fetch 返回的是一个 Promise 实例对象,不能直接取到里面的数据。而使用 await 关键字后,就相当于自动帮我们调用了 .then,把 Promise 解析后的数据直接赋值给变量。比如第一次用 await fetch... 获取响应对象 response,第二次再用 await response.json() 把 JSON 数据解析成 JS 对象。

        由于 await 是同步语法风格,我们就不能再用 .catch 来捕获错误,而需要使用 try catch finally 来捕获异常,比如 throw 抛出的错误才能在 catch 中处理。需要注意的是:只有在 async 声明的函数中才能使用 await。

4.删除数据

import React, { } from 'react';
import StuContext from './store/StuContext';
import StudentForm from './StudentForm';
const Student = (props) => {const Stx = React.useContext(StuContext)const [loading, setLoading] = React.useState(false)const [error, setError] = React.useState(null)const [isEdit, setIsEdit] = React.useState(null)const deleteData = React.useCallback(async () => {try {setLoading(true)setError(null)const res = await fetch(http://localhost:1337/api/students/${props.stu.documentId}, {method: 'delete'})if (!res.ok) {throw new Error('删除失败')}//修改成功后触发列表重新刷新Stx.fetchData()// const data = await res.json()// console.log('data', data)// 被删除的学生} catch (e) {console.log(e);setError(e)} finally {setLoading(false)}}, [])const Delete = () => {//删除学生deleteData()}const cancel = () => {setIsEdit(false)}return (<>{!isEdit &&<tr><td>{props.stu.name}</td><td>{props.stu.gender}</td><td>{props.stu.age}</td><td>{props.stu.address}</td><td><button onClick={Delete} >删除</button></td><td><button onClick={() => { setIsEdit(true) }} >修改</button></td></tr>}{isEdit && <StudentForm stu={props.stu} onCancel={cancel} />}{loading && <tr><td colSpan={5}>正在删除数据</td></tr>}{error && <tr><td colSpan={5}>删除失败</td></tr>}</>);
};export default Student;

        这是我们的删除请求,我们只需要在后面的对象中指名请求头为delete就可以去删除了。当然需要一个参数documentId去指名删除的哪一个。id不行在说一边我用的strapi不支持id去指定删除或者更新的表中的列。卡了一天了.............只不过一个点是Context我们用到了,因为我们

         

 

        每次在删除之后需要重新加载一遍数据,保证最新的数据在 页面上。

     <StuContext.Provider value={{ fetchData }}><div className="app"><button onClick={() => { loadDataHandler() }}>加载数据</button>{(!loading && !error) && <StudentList stus={stuData} />}{loading && <p>数据正在加载中...</p>}{error && <p>数据加载异常!</p>}</div></StuContext.Provider>

        就是这样然后我们在删除请求成功之后,执行一下重新加载的方法就好了。

5.创建以及更新请求

import React from 'react'
import './StudentForm.css'
import StuContext from './store/StuContext'
export default function StudentForm(props) {const Stx = React.useContext(StuContext)const [input, setInput] = React.useState({name: props.stu ? props.stu.name : '', age: props.stu ? props.stu.age : '',address: props.stu ? props.stu.address : '', gender: props.stu ? props.stu.gender : '男'})const [loading, setLoading] = React.useState(false)const [err, setErr] = React.useState(null)const addData = (async (input) => {try {setLoading(true)setErr(null)const res = await fetch('http://localhost:1337/api/students', {method: 'post',body: JSON.stringify({data: input}),headers: {'Content-Type': 'application/json'}})console.log('res.ok', res.ok)if (!res.ok) {throw new Error('添加失败')}//添加成功刷新列表Stx.fetchData()} catch (e) {console.log(e);setErr(e)} finally {setLoading(false)}})const updataData = (async (newStu, id) => {try {setErr(null)setLoading(true)const res = await fetch(http://localhost:1337/api/students/${id}, {method: 'PUT',body: JSON.stringify({ data: newStu }),headers: {'Content-Type': 'application/json'}})if (!res.ok) {throw new Error('修改出错')}Stx.fetchData()} catch (e) {setErr(e)} finally {setLoading(false)}})const nameChange = (e) => {setInput((preState) => ({ ...preState, name: e.target.value }))}const ageChange = (e) => {setInput((preState) => ({ ...preState, age: +e.target.value }))}const genderChange = (e) => {setInput((preState) => ({ ...preState, gender: e.target.value }))}const addressChange = (e) => {setInput((preState) => ({ ...preState, address: e.target.value }))}const handle = () => {addData(input)}const updataHandle = () => {updataData(input, props.stu.documentId)}return (<><tr className='student-form'><td><input type="text" onChange={nameChange} value={input.name} /></td><td><select name="" id="" onChange={genderChange} value={input.gender}><option value="男">男</option><option value="女">女</option></select></td><td><input type="text" onChange={ageChange} value={input.age} /></td><td><input type="text" onChange={addressChange} value={input.address} /></td><td>{props.stu && <><button onClick={() => { props.onCancel() }}>取消</button><button onClick={updataHandle}>修改</button></>}{!props.stu && <button onClick={handle}>添加</button>}</td></tr>{loading && <tr><td colSpan={5}>添加中</td></tr>}{err && <tr><td colSpan={5}>添加失败</td></tr>}</>)
}

        唯一不同的是我们在执行创建或者更新请求除了请求头不同以外,创建也就是添加新表元素需要传一个json格式的文本内容,也就是我们需要把js对象转化成json格式。正好对应我们响应体json格式需要转化成js对象我们用。以及指明请求体的格式,headers:{“Content-Type:'application/json'”}说明我们传过去的是json格式。包括更新,毕竟我们是传过去数据而不是get获取数据。这一点要注意。好了现在我们用fetch实现了post 增 delete删 put 改 get查了。虽然不熟练但至少有个思路怎么去数据库拿东西了。至于优化还是慢慢来吧。

         

 

http://www.dtcms.com/a/272657.html

相关文章:

  • ReentrantLock 与 Synchronized 的区别
  • 给MySQL做定时备份,一天3次
  • method_name字段是什么
  • 单片机基础(STM32-DAY2(GPIO))
  • Linux驱动06 --- UDP
  • 飞书AI技术体系
  • web 系统对接飞书三方登录完整步骤实战使用示例
  • 低温冷启动 高温热启动
  • OpenCV 图像进阶处理:特征提取与车牌识别深度解析
  • 醋酸镨:闪亮的稀土宝藏,掀开科技应用新篇章
  • Spring IoC 如何注入一些简单的值(比如配置文件里的字符串、数字)?
  • 【文献阅读】Depth Anything: Unleashing the Power of Large-Scale Unlabeled Data
  • MyBatis 使用教程及插件开发
  • 自动驾驶环境感知:天气数据采集与融合技术实战
  • AI-Sphere-Butler项目语音切换数字人管家形象功能老是开发不成功。
  • Oracle 数据库管理与维护实战指南(用户权限、备份恢复、性能调优)
  • 深度学习与图像处理案例 │ 基于深度学习的自动驾驶小车
  • GitHub上优秀的开源播放器项目介绍及优劣对比
  • 申请注册苹果iOS企业级开发者证书需要公司拥有什么规模条件
  • Nacos的基本功能以及使用Feign进行微服务间的通信
  • 【网络编程】 TCP 协议栈的知识汇总
  • ZW3D 二次开发-创建圆柱体
  • Qt cannot find C:\WINDOWS\TEMP\cctVBBgu: Invalid argument
  • QT5使用cmakelists引入Qt5Xlsx库并使用
  • 达梦数据库不兼容 SQL_NO_CACHE 报错解决方案
  • C++交叉编译工具链制作以及QT交叉编译环境配置
  • 生产环境CI/CD流水线构建与优化实践指南
  • 医院多部门协同构建知识库-指南库-预测模型三维网络路径研究
  • 12大产品规划工具对比:功能、价格与适用场景
  • (LeetCode 面试经典 150 题 ) 11. 盛最多水的容器 (贪心+双指针)