本文主要和大家分享電影蒐集的小應用react技術堆疊實踐,希望能幫助大家。
爬取豆瓣電影資訊並錄入MongoDB
電影列表展示,分類、搜尋
電影詳情展示及附件管理
註冊、登入
權限控制,一般使用者可以輸入、收藏,administrator輸入、修改、刪除
用戶中心,我的收藏清單
##一些總結前端前端使用了react,redux加redux-saga,對redux簡單總結一下,同時記錄一個前後介面呼叫有依賴關係的問題
多個元件和一個獨立出來的狀態物件直接互動,這樣之後,程式碼結構確實看上去更加清晰了。
action就是說明我要操作一個狀態了,怎麼操作是reducer的事,而所有狀態都儲存在store中,store發出動作並交由指定的reducer來處理
take,takeLatest,takeEvery,put,call,fork,select,使用過程中遇到一個介面呼叫有前後依賴關係的問題,比較有意思
/api/user/checkLogin,用來判斷是否登錄,在最外層的
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) }
state.loginStatus狀態還是false,上面就沒走到if中
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])) } }
//将获取附件的动作从 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) } }
使用pm2來管理node應用程式及部署程式碼,mongodb中開啟身分認證,使用token+ redis來做身分認證、在node中寫了寫單元測試,還是值得記錄的
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 是一個node單元測試框架,類似前端的jasmine,語法也相近
supertest 用來測試node介面的函式庫
#should nodejs斷言函式庫,可讀性很高
測試的一個例子,篇幅太長,就不放在這了
#相關推薦:
以上是電影蒐集的小應用react技術棧實踐的詳細內容。更多資訊請關注PHP中文網其他相關文章!