本文主要和大家分享電影蒐集的小應用react技術堆疊實踐,希望能幫助大家。
主要功能
爬取豆瓣電影資訊並錄入MongoDB
-
電影列表展示,分類、搜尋
電影詳情展示及附件管理
註冊、登入
權限控制,一般使用者可以輸入、收藏,administrator輸入、修改、刪除
用戶中心,我的收藏清單
- redux
多個元件和一個獨立出來的狀態物件直接互動,這樣之後,程式碼結構確實看上去更加清晰了。
action就是說明我要操作一個狀態了,怎麼操作是reducer的事,而所有狀態都儲存在store中,store發出動作並交由指定的reducer來處理
- redux-saga
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}
,整個步驟寫在一個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中不要處理太多操作,增加靈活性
使用pm2來管理node應用程式及部署程式碼,mongodb中開啟身分認證,使用token+ redis來做身分認證、在node中寫了寫單元測試,還是值得記錄的
- #使用jwt + redis 來做基於token的使用者身分認證
- 客戶端發起登入請求
- #服務端驗證使用者名稱密碼
- 驗證成功服務端產生一個token,回應給客戶端
- #客戶端之後的每次請求header中都帶上這個token
- 服務端對需要認證的介面要驗證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中文網其他相關文章!

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

SublimeText3 Linux新版
SublimeText3 Linux最新版

記事本++7.3.1
好用且免費的程式碼編輯器

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

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),