成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從前后端分別學(xué)習(xí)——注冊(cè)/登錄流程1

Gemini / 2331人閱讀

摘要:上面的寫法有個(gè)問題點(diǎn)擊按鈕發(fā)送請(qǐng)求后,客戶端一直收不到響應(yīng),就會(huì)報(bào)錯(cuò)其實(shí)傳送的時(shí)是一個(gè)異步的過程,里面還沒執(zhí)行完,外面就已經(jīng)執(zhí)行了,這邊可以用來解決下這個(gè)問題內(nèi)部返回一個(gè)對(duì)象,成功調(diào)用函數(shù),失敗調(diào)用函數(shù),這邊就默認(rèn)它會(huì)成功。

今天來研究一個(gè)小小的功能。當(dāng)我們進(jìn)入一個(gè)網(wǎng)站,它怎么判斷我是不是它的用戶?讓用戶登錄唄,如果它能正常登錄,它就是我的用戶唄?你有沒想過它是怎么判斷我是不是它用戶的?這次就來從前后端來講一講是怎么來實(shí)現(xiàn)這個(gè)功能的。

注冊(cè)

注冊(cè)一般流程可以簡(jiǎn)單的分為填寫信息,驗(yàn)證信息,提示用戶,寫入數(shù)據(jù)庫,注冊(cè)成功,大致流程如下圖所示。

這里用 JS 完成最簡(jiǎn)單的注冊(cè)流程,跑通邏輯,實(shí)際工作中遠(yuǎn)比這復(fù)雜。

簡(jiǎn)化驗(yàn)證環(huán)節(jié),只檢查郵箱是否輸入正確

注冊(cè)頁面

首先準(zhǔn)備一個(gè)最簡(jiǎn)單的注冊(cè)頁面如,上圖所示。

CSS 這里有兩個(gè)注意點(diǎn):

labellabel::after不同字?jǐn)?shù)的文字,兩端對(duì)齊

labelinput居中對(duì)齊用vertical-align:middle

*{padding:0;margin:0;box-sizing:border-box;}
body{
    display: flex;
    justify-content: center;
    align-items: center;
    height:100vh;
}
.sign_in_form{
    border:1px solid red;
    padding:20px;
    width:400px;
}
.row{
    margin-bottom: 10px;
}
h1{
    text-align: center;
}
input{
    vertical-align: middle;
}
label{
    vertical-align: middle;
    /*border:1px solid green;*/
    width:5em;
    display: inline-block;
    height:20px;
    line-height:20px;
    overflow: hidden;
    text-align: justify;
}
label::after{
    content:"";
    display: inline-block;
    /*border:1px solid blue;*/
    width:100%;
}

HTML 文件:

server 文件寫一個(gè)路由:當(dāng)我們?cè)L問首頁時(shí),跳轉(zhuǎn)頁面(這里默認(rèn)跳轉(zhuǎn)注冊(cè)頁面)

if (path === "/"){
    let string = fs.readFileSync("./signUp.html","utf8")
    response.setHeader("Content-Type","text/html;charset=utf-8")
    response.statusCode = 200
    response.write(string)
    response.end()
}

至此一個(gè)簡(jiǎn)單的登錄頁面就完成了,當(dāng)我們點(diǎn)擊注冊(cè)按鈕時(shí),就會(huì)像服務(wù)器發(fā)送一個(gè)請(qǐng)求。

發(fā)起 POST 請(qǐng)求


從上圖中我們可以看到,form表單可以發(fā)送一個(gè)GET,請(qǐng)求體變成查詢參數(shù)附在URL上,這是GET請(qǐng)求的一個(gè)特性,后臺(tái)通過讀取查詢參數(shù)就可以獲知請(qǐng)求信息。

這里就產(chǎn)生了一問題,賬戶密碼放在URL上太不安全了,別人一眼就能看到我的密碼,這樣肯定不行。

當(dāng)然form表單可以發(fā)起POST請(qǐng)求,但我們這里用ajax發(fā)送請(qǐng)求

let $signInForm = $(".sign_in_form")
let userInfoHash ={}
$signInForm.on("submit",function(e){
    e.preventDefault()
    let findUser = ["email","password","password_confirmation"]
    findUser.forEach((key)=>{
        let value = $(this).find(`input[name=${key}]`).val()
            userInfoHash[key] = value
        })
    $.post("/sign_up",hash).then(
        (response)=>{console.log(response)},
        (response)=>{console.log(response)}
    )
})

當(dāng)點(diǎn)擊注冊(cè)按鈕時(shí),通過findUser對(duì)象提供的key,找到對(duì)應(yīng)的value,用戶所填寫的信息,將被保存到userInfoHash中,通過POST請(qǐng)求傳遞給服務(wù)器。

服務(wù)器端做個(gè)路由,當(dāng)我請(qǐng)求路徑為sign_up且為POST請(qǐng)求,里面才會(huì)執(zhí)行。

if(path === "/sign_up" && method === "POST"){
    let body = []
    request.on("data",(chunk)=>{
        body.push(chunk)
    }).on("end",()=>{
        body = Buffer.concat(body).toString()
        console.log(body)
    })
    response.statusCode = 200
    response.end()
}

HTTP傳送方法是將數(shù)據(jù)一段一段上傳,所以在服務(wù)器端需要分別獲取數(shù)據(jù),然后在將他們拼接成一起,轉(zhuǎn)變成后端需要的字符串。

上面的寫法有個(gè)問題——點(diǎn)擊按鈕發(fā)送請(qǐng)求后,客戶端一直收不到響應(yīng),就會(huì)報(bào)錯(cuò)

Promise

其實(shí)HTTP傳送的時(shí)是一個(gè)異步的過程,里面還沒執(zhí)行完,外面就已經(jīng)執(zhí)行了,這邊可以用Promise來解決下這個(gè)問題

function readBody(request) {
    return new Promise((resolve,reject) =>{
        let body = []
        request.on("data",(chunk)=>{
            body.push(chunk)
        }).on("end",()=>{
            body = Buffer.concat(body).toString()
            resolve(body)
        })
    })
}

readBody內(nèi)部返回一個(gè)Promise對(duì)象,成功調(diào)用resolve函數(shù),失敗調(diào)用reject函數(shù),這邊就默認(rèn)它會(huì)成功。

所以上面代碼可以改寫成:

if(path === "/sign_up" && method === "POST"){
    readBody(request).then(
        (body)=>{
            console.log(body)
            response.statusCode = 200
            response.end()
        })
}

調(diào)用readBody函數(shù)后,因?yàn)?b>Promise返回的是一個(gè)對(duì)象可以直接在后面用.then()操作,成功執(zhí)行前面resolve函數(shù),失敗執(zhí)行后面reject函數(shù),不過這里要注意,如果真出錯(cuò)了真正的錯(cuò)誤信息在第二個(gè).then()resolve函數(shù)里,如下所示:

readBody(request).then(
        ()=>{console.log("success"),
        ()=>{console.log("錯(cuò)誤不執(zhí)行")}).then(
        ()=>{console.log("error")
    })
驗(yàn)證數(shù)據(jù)

后端成功拿到數(shù)據(jù)后,這個(gè)數(shù)據(jù)是字符串的形式,后端需要把它一步步拆解出來。

let bodyArr = body.split("&")
let userInfoHash = {}
bodyArr.forEach((e)=>{
    let part = e.split("=")
    userInfoHash[part[0]] = decodeURIComponent(part[1])
})
console.log(userInfoHash)

將拆分出來的數(shù)據(jù)一一對(duì)應(yīng)的保存到 userInfoHash里。

從這里我們不難看出,前端想盡一切辦法把數(shù)據(jù)辦成字符串傳給后端,后端在想盡一切辦法把前端傳遞來數(shù)據(jù)拆分成能用的格式。

當(dāng)然了,后臺(tái)響應(yīng)的內(nèi)容也是,前端拿到也是字符串。

當(dāng)拿到數(shù)據(jù)后,應(yīng)對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證,是否符合要求,這里簡(jiǎn)化起見,只驗(yàn)證email中有無@符號(hào)與passwordpassword_confirmation,如果正確就注冊(cè)成功。

response.setHeader("Content-Type","application/json;charset=utf-8")
let {email,password,password_confirmation} = userInfoHash
    if(email.indexOf("@") === -1){
        response.statusCode = 400
        response.write(`{
            "errors":{
                "email":"invalid"
            }
        }`)
    }else if(password !== password_confirmation){
        response.statusCode = 400
        response.write(`{
            "errors":{
                "password_confirmation":"mismatch"
            }
        }`)
    }else{
        response.statusCode = 200
        response.write(`{
            "success":"success"
        }`)
    }

這邊要注意的是@符號(hào)在nodejs會(huì)以%40的形式出現(xiàn)所以這邊需要對(duì)它進(jìn)行轉(zhuǎn)碼。

這里要注意的是后臺(tái)提供的響應(yīng)數(shù)據(jù)要用json的形式傳送給前端,如果格式不確定,前端那邊很難操作,也會(huì)造成問題的來源,后臺(tái)傳送數(shù)據(jù)時(shí)只需在響應(yīng)部分加上響應(yīng)頭response.setHeader("Content-Type","application/json;charset=utf-8"),前端拿到后會(huì)有相應(yīng)的轉(zhuǎn)換方法。

$.post("/sign_up",hash).then(
    (response)=>{
        let {success} = response
        if(success === "success"){
            window.location.herf = "/sign_in"
        }
    },
    (response)=>{
        let {email,password_confirmation} = response.responseJSON.errors
        if(email === "invalid"){
            $signInForm.find("input[name=email]").siblings(".error").text("郵箱錯(cuò)誤")
        }else if(password_confirmation === "mismatch"){
            $signInForm.find("input[name=password_confirmation]").siblings(".error").text("密碼不匹配")
    }
})

根據(jù)后臺(tái)響應(yīng)的信息,在頁面中提示用戶相關(guān)信息。

其實(shí)在用戶提交表單時(shí),前端應(yīng)該先阻止提交,判定一下用戶是否填寫正確,在發(fā)送請(qǐng)求,這樣在用戶填寫錯(cuò)誤時(shí)候無需發(fā)送請(qǐng)求,節(jié)約資源。

if(userInfoHash.email === ""){
    $signInForm.find("input[name=email]").siblings(".error").text("填郵箱呀")
    return
}else if(userInfoHash.password === ""){
    $signInForm.find("input[name=password]").siblings(".error").text("填密碼呀")
    return
}else if(userInfoHash.password_confirmation === ""){         
    $signInForm.find("input[name=password_confirmation]").siblings(".error").text("確認(rèn)密碼呀")
    return
}else if(userInfoHash.password !== userInfoHash.password_confirmation){
    $signInForm.find("input[name=password_confirmation]").siblings(".error").text("密碼不對(duì)呀")
    return
}

前端檢測(cè)用戶有沒填寫,如果沒填寫的話,直接提示用戶,無需提交后臺(tái)。

存儲(chǔ)數(shù)據(jù)

注冊(cè)成功后,把數(shù)據(jù)寫入數(shù)據(jù)庫,這里要注意,用戶隱私信息不能直接存儲(chǔ)在數(shù)據(jù)庫里,這里為了學(xué)習(xí)方便,故直接保存。

我們創(chuàng)建一個(gè)簡(jiǎn)單的文件,當(dāng)做數(shù)據(jù)庫,數(shù)據(jù)庫是以哈希表的形式存儲(chǔ)數(shù)據(jù)

let usersString = fs.readFileSync("./db/db","utf8") //讀取數(shù)據(jù)庫文件
let usersArr
try{
    usersArr = JSON.parse(usersString)    //轉(zhuǎn)化成對(duì)象
}catch(exception) {
    usersArr = []  
}
let isUse = false
for(let i = 0; i < usersArr.length; i++){    //遍歷 usersArr 
    if(usersArr[i].email === email){    //如果 usersArr 中存在用戶的郵箱,已經(jīng)注冊(cè)
        isUse = true
        break
    }
}
if(isUse){    //如果郵箱存在響應(yīng)前端操作提示用戶
    response.statusCode = 404
    response.write(`{
    "errors":{
        "email":"isUse"
        }
    }`)
}else{    //如果不存在將注冊(cè)信息寫入數(shù)據(jù)庫
    response.statusCode = 200
    usersArr.push(userInfoHash)    //存入剛剛讀取出來的 usersArr
    usersArr = JSON.stringify(usersArr)    // 轉(zhuǎn)變成字符串
    fs.writeFileSync("./db/db",usersArr)    //存入數(shù)據(jù)庫
    response.write(`{
        "successes":{
            "success":"success"
        }
    }`)
}

如果前面都層高,最后進(jìn)入寫數(shù)據(jù)庫環(huán)節(jié):讀取數(shù)據(jù)庫內(nèi)容——判斷用戶是否存在(這邊是判斷郵箱)——不存在,寫入數(shù)據(jù)庫;存在發(fā)送響應(yīng)信息。

至此注冊(cè)環(huán)節(jié)全部結(jié)束,這邊要特別注意,數(shù)據(jù)庫讀取出來的內(nèi)容是字符串

總結(jié)

數(shù)據(jù)類型在編程中非常重要,剛開始接觸時(shí),老把符合JSON語法的字符串當(dāng)成對(duì)象,弄清楚數(shù)據(jù)類型至關(guān)重要

前后端交互——字符串,不管是請(qǐng)求還是響應(yīng),都是字符串

后端與數(shù)據(jù)庫交互——字符串

沒有if...else解決不了問題,如果有加一個(gè)for循環(huán)

沒有console.log解決不了了bug,如果有那是console.log不夠多

網(wǎng)站登錄流程可參閱:從前后端分別學(xué)習(xí)——注冊(cè)/登錄流程2

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

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

相關(guān)文章

  • 從前后端分別學(xué)習(xí)——注冊(cè)/登錄流程2

    摘要:昨天研究了網(wǎng)站的注冊(cè)流程,感興趣的可以看下從前后端分別學(xué)習(xí)注冊(cè)登錄流程今天接著研究注冊(cè)登錄流程之登錄。為解決這個(gè)問題,引入,它是由一組隨機(jī)數(shù)組合的哈希表,當(dāng)用戶登錄成功,本來發(fā)放給用戶,現(xiàn)在變成發(fā)放給用戶。 昨天研究了網(wǎng)站的注冊(cè)流程,感興趣的可以看下:從前后端分別學(xué)習(xí)——注冊(cè)/登錄流程1 今天接著研究注冊(cè)/登錄流程之登錄。 登錄 首先來看一下登陸過程:showImg(https://s...

    happyhuangjinjin 評(píng)論0 收藏0
  • Vue中的驗(yàn)證登錄狀態(tài)

    摘要:用存儲(chǔ)用戶路由守衛(wèi)路由中設(shè)置的字段就在當(dāng)中每次跳轉(zhuǎn)的路徑登錄狀態(tài)下訪問頁面會(huì)跳到如果沒有訪問任何頁面。一個(gè)簡(jiǎn)單的保存登錄狀態(tài)的小。 Vue項(xiàng)目中實(shí)現(xiàn)用戶登錄及token驗(yàn)證 先說一下我的實(shí)現(xiàn)步驟: 使用easy-mock新建登錄接口,模擬用戶數(shù)據(jù) 使用axios請(qǐng)求登錄接口,匹配賬號(hào)和密碼 賬號(hào)密碼驗(yàn)證后, 拿到token,將token存儲(chǔ)到sessionStorage中,并跳轉(zhuǎn)到首...

    draveness 評(píng)論0 收藏0
  • react技術(shù)棧實(shí)踐(從前到后擼一個(gè)電影搜集應(yīng)用)

    摘要:其實(shí),該復(fù)雜的東西在哪放都復(fù)雜,只不過現(xiàn)在更清晰一點(diǎn)使用不好的地方就是太繁瑣了,定義各種各種組件。。。。。 之前做了個(gè)好電影搜集的小應(yīng)用,前端采用react,后端采用express+mongodb,最近又將組件間的狀態(tài)管理改成了redux,并加入了redux-saga來管理異步操作,記錄一些總結(jié) 在線地址 手機(jī)模式 源碼 主要功能 爬取豆瓣電影信息并錄入MongoDB 電影列表展示...

    tigerZH 評(píng)論0 收藏0
  • 邁出全棧第一步,vue+node+mysql獨(dú)立完成前后端分離的增刪改查流程

    摘要:本使用創(chuàng)建本地服務(wù)器,在就能完成全部流程,并不需要線上服務(wù)器。路徑要與后端接口一致。后端返回成功后,前端數(shù)據(jù)中對(duì)應(yīng)的元素也要?jiǎng)h掉,更新視圖??刂破骼锬靡粋€(gè)方法出來說一下吧,完整的代碼都在。讀取操作完成后調(diào)用釋放連接。 寫在前面 本文只是本人學(xué)習(xí)過程的一個(gè)記錄,并不是什么非常嚴(yán)謹(jǐn)?shù)慕坛?,希望和大家一起共同進(jìn)步。也希望大家能指出我的問題。適合有一定基礎(chǔ),志在全棧的前端初學(xué)者學(xué)習(xí),從點(diǎn)擊按鈕...

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

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

0條評(píng)論

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