亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

react技術(shù)棧實(shí)踐(從前到后擼一個(gè)電影搜集應(yīng)用)

tigerZH / 2230人閱讀

摘要:其實(shí),該復(fù)雜的東西在哪放都復(fù)雜,只不過(guò)現(xiàn)在更清晰一點(diǎn)使用不好的地方就是太繁瑣了,定義各種各種組件。。。。。

之前做了個(gè)好電影搜集的小應(yīng)用,前端采用react,后端采用express+mongodb,最近又將組件間的狀態(tài)管理改成了redux,并加入了redux-saga來(lái)管理異步操作,記錄一些總結(jié)
在線地址 手機(jī)模式

源碼

主要功能

爬取豆瓣電影信息并錄入MongoDB

電影列表展示,分類(lèi)、搜索

電影詳情展示及附件管理

注冊(cè)、登錄

權(quán)限控制,普通用戶可以錄入、收藏,administrator錄入、修改、刪除

用戶中心,我的收藏列表

一些總結(jié) 前端

前端使用了react,redux加redux-saga,對(duì)redux簡(jiǎn)單總結(jié)一下,同時(shí)記錄一個(gè)前后接口調(diào)用有依賴關(guān)系的問(wèn)題

redux

一句話總結(jié)redux,我覺(jué)的就是將組件之間的縱向的props傳遞和父子組件間的state愛(ài)恨糾纏給打平了,將一種縱向關(guān)系轉(zhuǎn)變成多個(gè)組件和一個(gè)獨(dú)立出來(lái)的狀態(tài)對(duì)象直接交互,這樣之后,代碼結(jié)構(gòu)確實(shí)看上去更加清晰了。

redux的核心概念,action,reducer,和store

action就是說(shuō)明我要操作一個(gè)狀態(tài)了,怎么操作是reducer的事,而所有狀態(tài)存儲(chǔ)在store中,store發(fā)出動(dòng)作并交由指定的reducer來(lái)處理

redux強(qiáng)制規(guī)范了我們對(duì)狀態(tài)的操作,只能在action和reducer這些東西中,這樣,原本錯(cuò)綜復(fù)雜的業(yè)務(wù)邏輯處理就換了個(gè)地,限制在了action和reducer中,組件看上去就很干凈了。其實(shí),該復(fù)雜的東西在哪放都復(fù)雜,只不過(guò)現(xiàn)在更清晰一點(diǎn)

使用redux不好的地方就是太繁瑣了,定義各種action,connect各種組件。。。?!,F(xiàn)在又出來(lái)一個(gè)Mobx,不明覺(jué)厲,反正大家都說(shuō)好~

redux-saga

redux-saga用來(lái)處理異步調(diào)用啥的,借助于generator,讓異步代碼看起來(lái)更簡(jiǎn)潔,常用的有take,takeLatest,takeEvery,put,call,fork,select,使用過(guò)程中遇到一個(gè)接口調(diào)用有前后依賴關(guān)系的問(wèn)題,比較有意思

描述一下:

有一個(gè)接口/api/user/checkLogin,用來(lái)判斷是否登錄,在最外層的組件的componentDidMount中觸發(fā)action來(lái)發(fā)起這個(gè)請(qǐng)求,并且接口返回狀態(tài)是登錄的話,還要發(fā)一個(gè)獲取用戶信息的

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)
}

然后我有一個(gè)電影詳情頁(yè)組件,在這個(gè)組件的componentDidMount中會(huì)發(fā)起/api/movies/${id}接口獲取電影信息,如果用戶是登錄狀態(tài)的話,還會(huì)發(fā)起一個(gè)獲取電影附件信息的接口/api/movies/${id}/attach整個(gè)步驟寫(xiě)在一個(gè)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)
}

用戶登錄了,進(jìn)到詳情,流程正常,但如果在詳情頁(yè)刷新了頁(yè)面,獲取附件的接口沒(méi)觸發(fā),原因是此時(shí)checkLogin接口還沒(méi)返回結(jié)果,state.loginStatus狀態(tài)還是false,上面就沒(méi)走到if中

一開(kāi)始想著怎么控制一些generator中yield的先后順序來(lái)解決(如果用戶沒(méi)有登錄的話,再發(fā)一個(gè)CHECK_LOAGIN,結(jié)果返回了流程再繼續(xù)),但存在CHECK_LOAGIN調(diào)用兩次,如果登錄了,還會(huì)再多一次獲取用戶信息的接口調(diào)用的情況,肯定不行

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) {
    //     //刷新頁(yè)面的時(shí)候,如果此時(shí)checklogin接口還沒(méi)返回?cái)?shù)據(jù)或還沒(méi)發(fā)出,應(yīng)觸發(fā)一個(gè)checklogin
    //     //checklogin返回后才能得到login狀態(tài)
    //     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的職責(zé),componentWillUpdate中合適的觸發(fā)獲取附件的動(dòng)作

//將獲取附件的動(dòng)作從 getMovieInfo這個(gè)generator中分離出來(lái)
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)) {
            //是登錄狀態(tài),并且movieInfo已經(jīng)返回時(shí)
            const { id } = this.props.match.params
            this.props.loadMovieAttach(id)
        }
}

總結(jié),合理使用組件的鉤子函數(shù),generator中不要處理太多操作,增加靈活性

后端

后端采用express和mongodb,也用到了redis,主要技術(shù)點(diǎn)有使用pm2來(lái)管理node應(yīng)用及部署代碼,mongodb中開(kāi)啟身份認(rèn)證,使用token+redis來(lái)做身份認(rèn)證、在node中寫(xiě)了寫(xiě)單元測(cè)試,還是值得記錄一下的

使用 jwt + redis 來(lái)做基于token的用戶身份認(rèn)證

基于token的認(rèn)證流程

客戶端發(fā)起登錄請(qǐng)求

服務(wù)端驗(yàn)證用戶名密碼

驗(yàn)證成功服務(wù)端生成一個(gè)token,響應(yīng)給客戶端

客戶端之后的每次請(qǐng)求header中都帶上這個(gè)token

服務(wù)端對(duì)需要認(rèn)證的接口要驗(yàn)證token,驗(yàn)證成功接收請(qǐng)求

這里采用jsonwebtoken來(lái)生成token,

jwt.sign(payload, secretOrPrivateKey, [options, callback])

使用express-jwt驗(yàn)證token(驗(yàn)證成功會(huì)把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時(shí)可以指定token的有效期,并且jsonwebtoken的verify方法也提供了選項(xiàng)來(lái)更新token的有效期,
但這里使用了express_jwt中間件,而express_jwt不提供方法來(lái)刷新token**

思路:

客戶端請(qǐng)求登錄成功,生成token

將此token保存在redis中,設(shè)置redis的有效期(例如1h)

新的請(qǐng)求過(guò)來(lái),先express_jwt驗(yàn)證token,驗(yàn)證成功, 再驗(yàn)證token是否在redis中存在,存在說(shuō)明有效

有效期內(nèi)客戶端新的請(qǐng)求過(guò)來(lái),提取token,更新此token在redis中的有效期

客戶端退出登錄請(qǐng)求,刪除redis中此token

具體代碼

使用 mocha + supertest + should 來(lái)寫(xiě)單元測(cè)試

測(cè)試覆蓋了所有接口,在開(kāi)發(fā)中,因?yàn)闆](méi)什么進(jìn)度要求就慢慢寫(xiě)了,寫(xiě)完一個(gè)接口就去寫(xiě)一個(gè)測(cè)試,測(cè)試寫(xiě)也還算詳細(xì),等測(cè)試通過(guò)了再前端調(diào)接口,整個(gè)過(guò)程還是挺有意思的

mocha 是一個(gè)node單元測(cè)試框架,類(lèi)似于前端的jasmine,語(yǔ)法也相近

supertest 用來(lái)測(cè)試node接口的庫(kù)

should nodejs斷言庫(kù),可讀性很高

測(cè)試的一個(gè)例子,篇幅太長(zhǎng),就不放在這了

最后

喜歡可以關(guān)注下,萬(wàn)一有福利呢。。。。。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/92233.html

相關(guān)文章

  • 技術(shù):小菜前端的技術(shù)是如何規(guī)劃和演進(jìn)的

    摘要:本文以管理者的視角,與大家分享下我自年月入職小菜后,與前端同學(xué)一起是如何規(guī)劃團(tuán)隊(duì)的技術(shù)棧的,這條技術(shù)棧上的技能點(diǎn)又是如何在不同童鞋不同業(yè)務(wù)中生長(zhǎng)出來(lái)的。 Scott 近兩年無(wú)論是面試還是線下線上的技術(shù)分享,遇到許許多多前端同學(xué),由于團(tuán)隊(duì)原因,個(gè)人原因,職業(yè)成長(zhǎng),技術(shù)方向,甚至家庭等等原因,在理想國(guó)與現(xiàn)實(shí)之間,在放棄與堅(jiān)守之間,搖擺不停,心酸硬抗,大家可以找我聊聊南聊聊北,對(duì)工程師的宿命...

    betacat 評(píng)論0 收藏0
  • 《從零構(gòu)建前后分離 WEB 項(xiàng)目》 序 - 開(kāi)源的意義

    摘要:盡量按照前端后端部署運(yùn)維來(lái)講,當(dāng)然中途涉及到跨域這種前后協(xié)調(diào)的還是無(wú)法避免捎帶一筆。關(guān)于我目前在寫(xiě)從零構(gòu)建前后分離項(xiàng)目系列,修正和補(bǔ)充以此為準(zhǔn)不斷更新的項(xiàng)目實(shí)踐地址彩蛋提前預(yù)覽下一章傳送門(mén) 序: 開(kāi)源的意義 本系列提前首發(fā)地址 背景 從事了近4年的互聯(lián)網(wǎng)行業(yè),逐漸擔(dān)當(dāng)過(guò)團(tuán)隊(duì)的前端到后端的負(fù)責(zé)人,和大家一樣從小白逐漸的成長(zhǎng)起來(lái),回首望去幾年前的博客還是那么稚嫩。 回首這幾年: 從一個(gè)ja...

    seasonley 評(píng)論0 收藏0
  • 《從零構(gòu)建前后分離 WEB 項(xiàng)目》 序 :開(kāi)源的意義

    摘要:從前端到后端到運(yùn)維,經(jīng)歷了幾次前后端架構(gòu)的演變,踩了無(wú)數(shù)的坑,度過(guò)無(wú)數(shù)難免的夜。為了工作或?qū)W習(xí),確實(shí)造過(guò)一些輪子,前端的后端的,也開(kāi)源出來(lái)過(guò)覺(jué)得能提高生產(chǎn)力的。 showImg(https://segmentfault.com/img/bVbgeXP?w=713&h=275); 序: 開(kāi)源的意義 本系列提前首發(fā)地址 背景 從事了近4年的互聯(lián)網(wǎng)行業(yè),逐漸擔(dān)當(dāng)過(guò)團(tuán)隊(duì)的前端到后端的負(fù)責(zé)人,和...

    J4ck_Chan 評(píng)論0 收藏0
  • 前端每周清單第 41 期 : Node 與 Rust、OpenCV 的火花,網(wǎng)絡(luò)安全二三事

    摘要:的網(wǎng)站仍然使用有漏洞庫(kù)上周發(fā)布了開(kāi)源社區(qū)安全現(xiàn)狀報(bào)告,發(fā)現(xiàn)隨著開(kāi)源社區(qū)的日漸活躍,開(kāi)源代碼中包含的安全漏洞以及影響的范圍也在不斷擴(kuò)大。與應(yīng)用安全是流行的服務(wù)端框架,本文即是介紹如何使用以及其他的框架來(lái)增強(qiáng)應(yīng)用的安全性。 showImg(https://segmentfault.com/img/remote/1460000012181337?w=1240&h=826); 前端每周清單專(zhuān)注...

    syoya 評(píng)論0 收藏0
  • 前端閱讀 - 收藏集 - 掘金

    摘要:實(shí)現(xiàn)不定期更新技巧前端掘金技巧,偶爾更新。統(tǒng)一播放效果實(shí)現(xiàn)打字效果動(dòng)畫(huà)前端掘金前端開(kāi)源項(xiàng)目周報(bào)前端掘金由出品的前端開(kāi)源項(xiàng)目周報(bào)第四期來(lái)啦。 Web 推送技術(shù) - 掘金騰訊云技術(shù)社區(qū)-掘金主頁(yè)持續(xù)為大家呈現(xiàn)云計(jì)算技術(shù)文章,歡迎大家關(guān)注! 作者:villainthr 摘自 前端小吉米 伴隨著今年 Google I/O 大會(huì)的召開(kāi),一個(gè)很火的概念--Progressive Web Apps ...

    lingdududu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<