电影搜集的小应用react技术栈实践
本文主要和大家分享电影搜集的小应用react技术栈实践,希望能帮助到大家。
主要功能
爬取豆瓣电影信息并录入MongoDB
电影列表展示,分类、搜索
电影详情展示及附件管理
注册、登录
权限控制,普通用户可以录入、收藏,administrator录入、修改、删除
用户中心,我的收藏列表
一些总结
前端
前端使用了react,redux加redux-saga,对redux简单总结一下,同时记录一个前后接口调用有依赖关系的问题
redux
一句话总结redux,我觉的就是将组件之间的纵向的props传递和父子组件间的state爱恨纠缠给打平了,将一种纵向关系转变成多个组件和一个独立出来的状态对象直接交互
,这样之后,代码结构确实看上去更加清晰了。
redux的核心概念,action,reducer,和store
action就是说明我要操作一个状态了,怎么操作是reducer的事,而所有状态存储在store中,store发出动作并交由指定的reducer来处理
redux强制规范了我们对状态的操作,只能在action和reducer这些东西中,这样,原本错综复杂的业务逻辑处理就换了个地,限制在了action和reducer中,组件看上去就很干净了。其实,该复杂的东西在哪放都复杂,只不过现在更清晰一点
使用redux不好的地方就是太繁琐了,定义各种action,connect各种组件。。。。。现在又出来一个Mobx,不明觉厉,反正大家都说好~
redux-saga
redux-saga用来处理异步调用啥的,借助于generator,让异步代码看起来更简洁,常用的有take,takeLatest,takeEvery,put,call,fork,select
,使用过程中遇到一个接口调用有前后依赖关系的问题,比较有意思
描述一下:
有一个接口/api/user/checkLogin,用来判断是否登录,在最外层的
组件的componentDidMount中触发action来发起这个请求,并且接口返回状态是登录的话,还要发一个获取用户信息的
function* checkLogin() { const res = yield Util.fetch('/api/user/checkLogin') yield put(recieveCheckLogin(!res.code)) if (!res.code) { //已登录 yield put(fetchUinfo()) } } export function* watchCheckLogin() { yield takeLatest(CHECK_LOAGIN, checkLogin) }
然后我有一个电影详情页组件,在这个组件的componentDidMount中会发起
/api/movies/${id}
接口获取电影信息,如果用户是登录状态的话,还会发起一个获取电影附件信息的接口/api/movies/${id}/attach
,整个步骤写在一个generator中
function* getItemMovie(id) { return yield Util.fetch(`/api/movies/${id}`) } function* getMovieAttach(id) { return yield Util.fetch(`/api/movies/${id}/attach`) } function* getMovieInfo(action) { const { movieId } = action let { login } = yield select(state => state.loginStatus) const res = yield call(getItemMovie, movieId) yield put(recieveItemMovieInfo(res.data[0])) if (res.data[0].attachId && login) { const attach = yield call(getMovieAttach, movieId) yield put(recieveMovieAttach(attach.data[0])) } } export function* watchLoadItemMovie() { yield takeLatest(LOAD_ITEM_MOVIE, getMovieInfo) }
用户登录了,进到详情,流程正常,但如果在详情页刷新了页面,获取附件的接口没触发,原因是此时checkLogin接口还没返回结果,
state.loginStatus
状态还是false,上面就没走到if中一开始想着怎么控制一些generator中yield的先后顺序来解决(如果用户没有登录的话,再发一个CHECK_LOAGIN,结果返回了流程再继续),但存在CHECK_LOAGIN调用两次,如果登录了,还会再多一次获取用户信息的接口调用的情况,肯定不行
function* getMovieInfo(action) { const { movieId } = action let { login } = yield select(state => state.loginStatus) const res = yield call(getItemMovie, movieId) yield put(recieveItemMovieInfo(res.data[0])) // if (!login) { // //刷新页面的时候,如果此时checklogin接口还没返回数据或还没发出,应触发一个checklogin // //checklogin返回后才能得到login状态 // yield put({ // type: CHECK_LOAGIN // }) // const ret = yield take(RECIEVE_CHECK_LOAGIN) // login = ret.loginStatus // } if (res.data[0].attachId && login) { const attach = yield call(getMovieAttach, movieId) yield put(recieveMovieAttach(attach.data[0])) } }
最终的办法,分解generator的职责,componentWillUpdate中合适的触发获取附件的动作
//将获取附件的动作从 getMovieInfo这个generator中分离出来 function* getMovieInfo(action) { const { movieId } = action const res = yield call(getItemMovie, movieId) yield put(recieveItemMovieInfo(res.data[0])) } function* watchLoadItemMovie() { yield takeLatest(LOAD_ITEM_MOVIE, getMovieInfo) } function* watchLoadAttach() { while (true) { const { movieId } = yield take(LOAD_MOVIE_ATTACH) const { attachId } = yield select(state => state.detail.movieInfo) const attach = yield call(getMovieAttach, movieId) yield put(recieveMovieAttach(attach.data[0])) } } //组件中 componentWillUpdate(nextProps) { if (nextProps.loginStatus && (nextProps.movieInfo!==this.props.movieInfo)) { //是登录状态,并且movieInfo已经返回时 const { id } = this.props.match.params this.props.loadMovieAttach(id) } }
总结,合理使用组件的钩子函数,generator中不要处理太多操作,增加灵活性
后端
后端采用express和mongodb,也用到了redis,主要技术点有使用pm2来管理node应用及部署代码
,mongodb中开启身份认证,使用token+redis来做身份认证、在node中写了写单元测试,还是值得记录一下的
使用 jwt + redis 来做基于token的用户身份认证
基于token的认证流程
客户端发起登录请求
服务端验证用户名密码
验证成功服务端生成一个token,响应给客户端
客户端之后的每次请求header中都带上这个token
服务端对需要认证的接口要验证token,验证成功接收请求
这里采用jsonwebtoken来生成token,
jwt.sign(payload, secretOrPrivateKey, [options, callback])
使用express-jwt验证token(验证成功会把token信息放在request.user中)
express_jwt({ secret: SECRET, getToken: (req)=> { if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') { return req.headers.authorization.split(' ')[1]; } else if (req.query && req.query.token) { return req.query.token; } return null; } }
为什么使用redis
**采用jsonwebtoken生成token时可以指定token的有效期,并且jsonwebtoken的verify方法也提供了选项来更新token的有效期,
但这里使用了express_jwt中间件,而express_jwt不提供方法来刷新token**
思路:
客户端请求登录成功,生成token
将此token保存在redis中,设置redis的有效期(例如1h)
新的请求过来,先express_jwt验证token,验证成功, 再验证token是否在redis中存在,存在说明有效
有效期内客户端新的请求过来,提取token,更新此token在redis中的有效期
客户端退出登录请求,删除redis中此token
具体代码
使用 mocha + supertest + should 来写单元测试
测试覆盖了所有接口,在开发中,因为没什么进度要求就慢慢写了,写完一个接口就去写一个测试,测试写也还算详细,等测试通过了再前端调接口,整个过程还是挺有意思的
mocha 是一个node单元测试框架,类似于前端的jasmine,语法也相近
supertest 用来测试node接口的库
should nodejs断言库,可读性很高
测试的一个例子,篇幅太长,就不放在这了
相关推荐:
以上是电影搜集的小应用react技术栈实践的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

从主屏幕中删除了重要内容并试图将其取回?您可以通过多种方式将应用程序图标放回屏幕。我们已经讨论了您可以遵循的所有方法,并将应用程序图标放回主屏幕如何在iPhone中撤消从主屏幕中删除正如我们之前提到的,有几种方法可以在iPhone上恢复此更改。方法1–替换应用程序库中的应用程序图标您可以直接从应用程序库将应用程序图标放置在主屏幕上。第1步–横向滑动以查找应用程序库中的所有应用程序。步骤2–找到您之前删除的应用程序图标。步骤3–只需将应用程序图标从主库拖动到主屏幕上的正确位置即可。这是将应用程序图

23年9月国防科大、京东和北理工的论文“DeepModelFusion:ASurvey”。深度模型融合/合并是一种新兴技术,它将多个深度学习模型的参数或预测合并为一个模型。它结合了不同模型的能力来弥补单个模型的偏差和错误,以获得更好的性能。而大规模深度学习模型(例如LLM和基础模型)上的深度模型融合面临着一些挑战,包括高计算成本、高维参数空间、不同异构模型之间的干扰等。本文将现有的深度模型融合方法分为四类:(1)“模式连接”,通过一条损失减少的路径将权重空间中的解连接起来,以获得更好的模型融合初

Java框架与React框架的整合:步骤:设置后端Java框架。创建项目结构。配置构建工具。创建React应用。编写RESTAPI端点。配置通信机制。实战案例(SpringBoot+React):Java代码:定义RESTfulAPI控制器。React代码:获取并显示API返回的数据。

写在前面&笔者的个人理解基于图像的3D重建是一项具有挑战性的任务,涉及从一组输入图像推断目标或场景的3D形状。基于学习的方法因其直接估计3D形状的能力而受到关注。这篇综述论文的重点是最先进的3D重建技术,包括生成新颖的、看不见的视图。概述了高斯飞溅方法的最新发展,包括输入类型、模型结构、输出表示和训练策略。还讨论了尚未解决的挑战和未来的方向。鉴于该领域的快速进展以及增强3D重建方法的众多机会,对算法进行全面检查似乎至关重要。因此,本研究对高斯散射的最新进展进行了全面的概述。(大拇指往上滑

OpenAI发布的GPT-4o模型无疑是一个巨大的突破,特别是在其能够处理多种输入媒介(文本、音频、图片)并生成相应输出方面。这种能力使得人机交互更加自然和直观,极大地提升了AI的实用性和可用性。GPT-4o的几个关键亮点包括:高度可扩展性、多媒体输入输出、自然语言理解能力的进一步提升等等。1.跨媒介输入/输出:GPT-4o+能够接受文本、音频和图片的任意组合作为输入,并直接生成这些媒介的输出。这打破了传统AI模型仅处理单一输入类型的限制,使得人机交互更加灵活和多样化。这一创新有助于推动智能助手

Go语言:简介和优势Go语言是一款由Google开发的开源编程语言,以其并发性和高效性着称。它的关键功能包括并发编程模型(基于Goroutine和channel)、静态类型系统和垃圾收集器。 Go语言独特的优势在于:高效的并发性出色的性能简洁的语法开箱即用的工具

Vue.js适合中小型项目和快速迭代,React适用于大型复杂应用。1)Vue.js易于上手,适用于团队经验不足或项目规模较小的情况。2)React的生态系统更丰富,适合有高性能需求和复杂功能需求的项目。

在当今软件开发领域中,Go语言和JavaScript被广泛应用于不同的领域和场景。Go语言作为一种静态类型、编译型的语言,适用于后端服务和系统级编程;而JavaScript则是一种动态类型、解释型的语言,主要用于前端开发和交互设计。虽然两者在语法、运行环境等方面有着明显的不同,但它们之间的交流与融合也成为了软件开发者们关注的话题。随着前后端分离的发展趋势,前
