框架流程

一、瀏覽器發(fā)送請求

1、用戶輸入網址
http://127.0.0.1/
2、瀏覽器根據(jù)請求轉變HTTP的請求包
GET / HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

二、服務器接收到請求

1、http模塊里實例化的server對象,server對象監(jiān)聽每一次瀏覽器發(fā)送過來的請求,每次的請求都會觸發(fā)request事件
this.server.on("request",(req,res)=>{})
2、將HTTP的請求包轉換成req的請求對象,并且傳入到請求事件觸發(fā)的函數(shù)中。
3、會創(chuàng)建生成一個res響應對象,這個對象可以幫助我們快速的實現(xiàn)HTTP的響應。

三、解析請求路徑,調用不同的頁面渲染函數(shù)

1、正則匹配方式進行對路徑的匹配。
2、以匹配的正則字符串作為KEY,找到需要調用執(zhí)行的渲染函數(shù)
//循環(huán)匹配正則路徑
for(let key in this.reqEvent){
    let regStr = key
    let reg = new RegExp(regStr,'igs');
    if(reg.test(req.url)){
        this.reqEvent[key](req,res);
        resState = true
        break;
    }
}
3、調用頁面的執(zhí)行函數(shù),執(zhí)行模板渲染
app.on('/movies/[01]',(req,res)=>{}) //這里的箭頭函數(shù)即為真正匹配到的頁面執(zhí)行的函數(shù)
4、調用模板的渲染函數(shù)
res.render(movies[index],'./template/index1.html')
5、執(zhí)行渲染函數(shù)
function render(options,path) {
    fs.readFile(path,{encoding:"utf-8",flag:"r"},(err,data)=>{
        if(err){
            console.log(err)
        }else{
            try{
                data = replaceArr(data,options)
                data = replaceVar(data,options)
            }catch(error){
                console.log(error)
            }
            this.end(data)
            
        }
    })
}
6、數(shù)組變量的替換
function replaceArr(data,options){
    //匹配循環(huán)的變量,并且替換循環(huán)的內容
    let reg = /\{\%for \{(.*?)\} \%\}(.*?)\{\%endfor\%\}/igs
    while(result = reg.exec(data)){
        let strKey = result[1].trim();//提取變量時,去掉左右兩邊的空格
        //通過key值獲取數(shù)組的內容
        let strValueArr = options[strKey]
        let listStr = ""
        strValueArr.forEach((item,i) => {
            //替換每一項內容里的變量
            listStr = listStr + replaceVar(result[2],{"item":item})
        });
        data = data.replace(result[0],listStr)
    }
    return data
}
7、單個變量的替換
function replaceVar(data,options) {
    //匹配普通的變量,并且替換內容
    let reg = /\{\{(.*?)\}\}/igs
    let result;
    while (result = reg.exec(data)){
        //去除兩邊的空白
        let strKey = result[1].trim();
        //options.item
        let strValue = eval('options.'+strKey);//執(zhí)行字符串作為JS表達式,并將計算出來的結果返回
        data = data.replace(result[0],strValue)
    }
    return data
}

四、如果是請求靜態(tài)文件,那么就按照靜態(tài)文件的形式輸出

1、首先判斷是否響應過,如果沒有響應過,可以判斷是否為靜態(tài)文件,如果是靜態(tài)文件就正常的輸出
2、否則就輸出404
if(!resState){
    try{
        if(pathObj.dir==this.staticDir){
                res.setHeader("content-type",this.getContentType(pathObj.ext))
                let rs = fs.createReadStream('./static/'+pathObj.base)
                rs.pipe(res)
        }else{
            res.setHeader("content-type","text/html;charset=utf-8")
            res.end("<h1>404!頁面找不到</h1>")
        }
    }catch(error){
        console.log(error)
    }
}

五、RES響應對象將res設置的內容最終轉化成http的響應包

HTTP/1.1 200 OK
content-type: text/html;charset=utf-8
Date: Thu, 23 Jul 2020 12:17:19 GMT
Connection: keep-alive
Content-Length: 53

正文內容

六、瀏覽器解析響應包,并將html渲染在頁面上

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容