Http 請(qǐng)求頭響應(yīng)頭 + enctype屬性 + cookie + async

2018-6-26更新

304狀態(tài)碼 : Not Modified ---- 頁(yè)面未被修改,緩存是最新的

304自從上次請(qǐng)求后,請(qǐng)求的網(wǎng)頁(yè)未修改過。服務(wù)器返回此響應(yīng)時(shí),不會(huì)返回網(wǎng)頁(yè)內(nèi)容。 如果網(wǎng)頁(yè)自請(qǐng)求者上次請(qǐng)求后再也沒有更改過,您應(yīng)將服務(wù)器配置為返回此響應(yīng)(稱為 If-Modified-Since HTTP 標(biāo)頭)。

當(dāng)一個(gè)客戶端(通常是瀏覽器)向web服務(wù)器發(fā)送一個(gè)請(qǐng)求,如果web服務(wù)器返回304響應(yīng),則表示此請(qǐng)求的本地緩存是最新的,可以直接使用。這種方法可以節(jié)省帶寬,避免重復(fù)響應(yīng)。

304狀態(tài)碼總結(jié):
  • modified:是修改的意思 -------- ( not modified未被修改 )
  • 304狀態(tài)碼表示自上次請(qǐng)求后,請(qǐng)求的網(wǎng)頁(yè)未被修改過,緩存是最新的,可以直接使用。
  • 當(dāng)狀態(tài)碼是304的時(shí)候,服務(wù)器返回的body為空
  • 304狀態(tài)碼和Last-Modified ,If-Modified-Since有關(guān) ----------- ( 重要 )
  • Last-Modified : 是由服務(wù)器往客戶端發(fā)送的 HTTP 頭
  • If-Modified-Since : 是由客戶端往服務(wù)器發(fā)送的 HTTP 頭
  • 304狀態(tài)碼和If-None-Match,ETags有關(guān) ------------------------- ( 重要 )
  • If-None-Match,和ETags常用來判斷當(dāng)前請(qǐng)求資源是否改變。
  • 區(qū)別:(Last-Modified,If-Modified-Since )(If-None-Match, ETags)
    Last-Modified和IF-Modified-Since只判斷資源的最后修改時(shí)間,
    而ETags和If-None-Match可以是資源任何的任何屬性,比如資源的MD5等。
  • ETags和If-None-Match的工作原理是在HTTP Response中添加ETags信息。當(dāng)客戶端再次請(qǐng)求該資源時(shí),將在HTTP Request中加入If-None-Match信息(ETags的值)。如果服務(wù)器驗(yàn)證資源的ETags沒有改變(該資源沒有改變),將返回一個(gè)304狀態(tài),否則,服務(wù)器將返回200狀態(tài),并返回該資源和新的ETags。
  • Etag的優(yōu)先級(jí)高于Last-Modified --------------------------------------- ( 重要 )
  • (Etag 和 If-None-Match)優(yōu)于(Last-Modified 和 If-Modified-Since)的地方:
    (1)、Last-Modified標(biāo)注的最后修改只能精確到秒級(jí),如果某些文件在1秒鐘以內(nèi),被修改多次的話,它將不能準(zhǔn)確標(biāo)注文件的修改時(shí)間;
    (2)、如果某些文件會(huì)被定期生成,當(dāng)有時(shí)內(nèi)容并沒有任何變化,但Last-Modified卻改變了,導(dǎo)致文件沒法使用緩存;
    (3)、有可能存在服務(wù)器沒有準(zhǔn)確獲取文件修改時(shí)間,或者與代理服務(wù)器時(shí)間不一致等情形。
    然而,Etag是服務(wù)器自動(dòng)生成或者由開發(fā)者生成的對(duì)應(yīng)資源在服務(wù)器端的唯一標(biāo)識(shí)符,能夠更加準(zhǔn)確的控制緩存。
ETag 和 If-None-Match
  • ETag和If-None-Match的工作原理是在HTTP Response中添加ETags信息。當(dāng)客戶端再次請(qǐng)求該資源時(shí),將在HTTP Request中加入If-None-Match信息(ETags的值)。如果服務(wù)器驗(yàn)證資源的ETags沒有改變(該資源沒有改變),將返回一個(gè)304狀態(tài);否則,服務(wù)器將返回200狀態(tài),并返回該資源和新的ETags。
什么是”Etag”? --------------------------- ( 重要 )

典型的Web資源可以一個(gè)Web頁(yè),但也可能是JSON或XML文檔。服務(wù)器單獨(dú)負(fù)責(zé)判斷記號(hào)是什么及其含義,并在HTTP響應(yīng)頭中將其傳送到客戶端,以下是服務(wù)器端返回的格式:
ETag: "50b1c1d4f775c61:df3"
客戶端的查詢更新格式是這樣的:
If-None-Match: W/"50b1c1d4f775c61:df3"
如果ETag沒改變,則返回狀態(tài)304然后不返回body,這也和Last-Modified一樣。
Etag主要在斷點(diǎn)下載時(shí)比較有用。
說白了,
ETag 實(shí)體標(biāo)簽: 一般為資源實(shí)體的哈希值
即ETag就是服務(wù)器生成的一個(gè)標(biāo)記,用來標(biāo)識(shí)返回值是否有變化。
且Etag的優(yōu)先級(jí)高于Last-Modified。

ETag的原理

它的原理是這樣的,當(dāng)瀏覽器請(qǐng)求服務(wù)器的某項(xiàng)資源(A)時(shí), 服務(wù)器根據(jù)A算出一個(gè)哈希值(3f80f-1b6-3e1cb03b)并通過 ETag 返回給瀏覽器,瀏覽器把"3f80f-1b6-3e1cb03b" 和 A 同時(shí)緩存在本地,當(dāng)下次再次向服務(wù)器請(qǐng)求A時(shí),會(huì)通過類似 If-None-Match: "3f80f-1b6-3e1cb03b" 的請(qǐng)求頭把ETag發(fā)送給服務(wù)器,服務(wù)器再次計(jì)算A的哈希值并和瀏覽器返回的值做比較,如果發(fā)現(xiàn)A發(fā)生了變化就把A返回給瀏覽器(200),如果發(fā)現(xiàn)A沒有變化就給瀏覽器返回一個(gè)304未修改。這樣通過控制瀏覽器端的緩存,可以節(jié)省服務(wù)器的帶寬,因?yàn)榉?wù)器不需要每次都把全量數(shù)據(jù)返回給客戶端。

Last-Modified 和 If-Modified-Since

再次請(qǐng)求本地存在的 cache 頁(yè)面時(shí),客戶端會(huì)通過 If-Modified-Since 頭將先前服務(wù)器端發(fā)過來的 Last-Modified 最后修改時(shí)間戳發(fā)送回去,這是為了讓服務(wù)器端進(jìn)行驗(yàn)證,通過這個(gè)時(shí)間戳判斷客戶端的頁(yè)面是否是最新的,如果不是最新的,則返回新的內(nèi)容,如果是最新的,則 返回 304 告訴客戶端其本地 cache 的頁(yè)面是最新的,于是客戶端就可以直接從本地加載頁(yè)面了

  • 這樣在網(wǎng)絡(luò)上傳輸?shù)臄?shù)據(jù)就會(huì)大大減少,同時(shí)也減輕了服務(wù)器的負(fù)擔(dān)。
什么是”Last-Modified”? --------------- ( 重要 )

在瀏覽器第一次請(qǐng)求某一個(gè)URL時(shí),服務(wù)器端的返回狀態(tài)會(huì)是200,內(nèi)容是你請(qǐng)求的資源,同時(shí)有一個(gè)Last-Modified的屬性標(biāo)記此文件在服務(wù)期端最后被修改的時(shí)間,格式類似這樣:
Last-Modified: Fri, 12 May 2006 18:53:33 GMT
客戶端第二次請(qǐng)求此URL時(shí),根據(jù) HTTP 協(xié)議的規(guī)定,瀏覽器會(huì)向服務(wù)器傳送 If-Modified-Since 報(bào)頭,詢問該時(shí)間之后文件是否有被修改過:
If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
如果服務(wù)器端的資源沒有變化,則自動(dòng)返回 HTTP 304 (Not Changed.)狀態(tài)碼,內(nèi)容為空,這樣就節(jié)省了傳輸數(shù)據(jù)量。當(dāng)服務(wù)器端代碼發(fā)生改變或者重啟服務(wù)器時(shí),則重新發(fā)出資源,返回和第一次請(qǐng)求時(shí)類似。從而保證不向客戶端重復(fù)發(fā)出資源,也保證當(dāng)服務(wù)器有變化時(shí),客戶端能夠得到最新的資源。

ETage 和 If-None-Match https://www.cnblogs.com/softidea/p/5986339.html
Last-Modified https://blog.csdn.net/taipingliebeiluo/article/details/5842766
https://www.cnblogs.com/huenchao/p/6104709.html





(一) 請(qǐng)求頭-請(qǐng)求報(bào)文頭屬性

(1) Accept

請(qǐng)求報(bào)文通過 Accept 報(bào)文頭屬性告訴服務(wù)端 - 客戶端接受什么類型的響應(yīng)。
( Accept : 接受 )

  • 瀏覽器發(fā)送的accept字段只是建議值,服務(wù)器是否使用這個(gè)值由服務(wù)端程序決定。
    如果服務(wù)端按Restful規(guī)范開發(fā)接口的話,可以考慮根據(jù)accept的不同值返回不同格式的內(nèi)容。同一份數(shù)據(jù)可以按json, xml格式分別輸出。
  • 如果服務(wù)器無法返回text/html類型的數(shù)據(jù),服務(wù)器應(yīng)該返回一個(gè)406錯(cuò)誤(non acceptable)
  • 通配符 * 代表任意類型
  • Accept: */* 代表瀏覽器可以處理所有類型,(一般瀏覽器發(fā)給服務(wù)器都是發(fā)這個(gè))
Accept:text/html:HTML格式的文本文檔
Accept:text/plain:普通的ASCⅡ文本文檔
Accept:image/jpeg:JPEG格式的圖片
Accept:image/gif:GIF格式的圖片

(2) Content-Type

Content-Type屬性指定請(qǐng)求和響應(yīng)的HTTP內(nèi)容類型。 (內(nèi)容)
如果未指定 ContentType,默認(rèn)為text/html。

  • Content-Type 是Http的實(shí)體首部字段,用于說明請(qǐng)求或返回的消息主體是用何種方式編碼,在request header和response header里都存在。
  • enctype 是編碼方式的意思

Content-Type:請(qǐng)求的與實(shí)體對(duì)應(yīng)的MIME信息  -------------------------------------------- (重要)


1.text/html
2.text/plain
3.text/css
4.text/javascript

5.application/x-www-form-urlencoded
6.multipart/form-data
7.application/json
8.application/xml

前面幾個(gè)都很好理解,都是html,css,javascript的文件類型,后面四個(gè)是POST的發(fā)包方式。






(1) Content-Type: application/json;
Content-Type: application/json 用來告訴服務(wù)端消息主體是序列化后的 JSON 字符串。
傳遞的是一個(gè)json對(duì)象,并不是直接丟一個(gè)對(duì)象過去,需要進(jìn)行序列化,JSON.stringify(data)







(2) Content-Type: application/x-www-form-urlencoded
application/x-www-form-urlencoded是常用的表單發(fā)包方式,普通的表單提交,或者js發(fā)包,默認(rèn)都是通過這種方式

  表單:
    <form enctype="application/x-www-form-urlencoded"    ----------------------------?。?!
          action="http://homeway.me/post.php" method="POST">
       <input type="text" name="name" value="homeway">
       <input type="text" name="key" value="nokey">
       <input type="submit" value="submit">
     </form>
  務(wù)器收到的raw header:
     Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
     Accept-Encoding:gzip, deflate
     Accept-Language:zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4,gl;q=0.2,de;q=0.2
     Cache-Control:no-cache
     Connection:keep-alive
     Content-Length:17
     Content-Type:application/x-www-form-urlencoded     ------------------------------?。?!
  服務(wù)器收到的raw body 
     name=homeway&key=nokey                             ------------------------------!?。?






(3) Content-Type:multipart/form-data;
我們使用表單上傳文件時(shí),必須讓 <form> 表單的 enctype 等于 multipart/form-data。







(4) Content-Type: text/xml
微信用的是這種數(shù)據(jù)格式發(fā)送請(qǐng)求的。


accept-Charset:瀏覽器通過這個(gè)頭告訴服務(wù)器,它支持哪種字符集。



accept-encoding:瀏覽器通過這個(gè)頭告訴服務(wù)器,它支持哪種壓縮格式。
例如: Accept-Encoding: gzip, deflate



accept-language:瀏覽器通過這個(gè)頭告訴服務(wù)器,它的語言環(huán)境。
例如: Accept-Language: en-us



User-Agent
作用:告訴HTTP服務(wù)器, 客戶端使用的操作系統(tǒng)和瀏覽器的名稱和版本.
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) .....




Authorization:HTTP授權(quán)的授權(quán)證書
例如:Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==




Cache-Control:指定請(qǐng)求和響應(yīng)遵循的緩存機(jī)制
例如: 
Cache-Control:Public    可以被任何緩存所緩存()
Cache-Control:Private   內(nèi)容只緩存到私有緩存中
Cache-Control:no-cache  所有內(nèi)容都不會(huì)被緩存
Cache-Control:max-age=20 到期時(shí)間
Cache-Control:'max-age=20, Public' 設(shè)置多個(gè)值時(shí),用逗號(hào)進(jìn)行分隔




Connection:瀏覽器通過這個(gè)頭告訴服務(wù)器,請(qǐng)求完后是斷開鏈接還是維持鏈接。
例如:
Connection: close
Connection:keep-alive 持續(xù)鏈接





Cookie:將cookie的值發(fā)送給HTTP 服務(wù)器
作用:HTTP請(qǐng)求發(fā)送時(shí),會(huì)把保存在該請(qǐng)求域名下的所有cookie值一起發(fā)送給web服務(wù)器。




referer:瀏覽器通過這個(gè)頭告訴服務(wù)器,客戶機(jī)是哪個(gè)頁(yè)面來的(防盜鏈)。
先前網(wǎng)頁(yè)的地址,當(dāng)前請(qǐng)求網(wǎng)頁(yè)緊隨其后,即來路



host:瀏覽器通過這個(gè)頭告訴服務(wù)器,它想訪問哪臺(tái)主機(jī)。



if-modified-since:瀏覽器通過這個(gè)頭告訴服務(wù)器,緩存數(shù)據(jù)的時(shí)間



(二) HTML <form> 標(biāo)簽的 enctype 屬性

enctype 是編碼方式的意思

<form enctype="value">
<form enctype="value">


value值:
(1) application/x-www-form-urlencoded   在發(fā)送前編碼所有字符(默認(rèn))

(2) multipart/form-data 不對(duì)字符編碼。在使用包含文件上傳控件的表單時(shí),必須使用該值。

(3) text/plain  空格轉(zhuǎn)換為 "+" 加號(hào),但不對(duì)特殊字符編碼。

(三) Cookie

Cookie 是服務(wù)器保存在瀏覽器的一小段文本信息,每個(gè) Cookie 的大小一般不能超過4KB。瀏覽器每次向服務(wù)器發(fā)出請(qǐng)求,就會(huì)自動(dòng)附上這段信息。

  • cookie是服務(wù)器保存在瀏覽器上的一段文本信息
  • 大小一般不能超過4kb
  • 瀏覽器向服務(wù)器發(fā)送請(qǐng)求時(shí),會(huì)自動(dòng)附上這段文本信息

作用:

cookie主要用來區(qū)分兩個(gè)請(qǐng)求是否來自同一個(gè)瀏覽器 ,以及保存一些狀態(tài)信息。

常用場(chǎng)合:

  • 對(duì)話(session)管理:保存登錄、購(gòu)物車等需要記錄的信息。
  • 個(gè)性化:保存用戶的偏好,比如網(wǎng)頁(yè)的字體大小、背景色等等。
  • 追蹤:記錄和分析用戶行為。

cookie包含的信息:

  • Cookie 的名字
  • Cookie 的值(真正的數(shù)據(jù)寫在這里面)
  • 到期時(shí)間
  • 所屬域名(默認(rèn)是當(dāng)前域名)
  • 生效的路徑(默認(rèn)是當(dāng)前網(wǎng)址)

Cookie 對(duì)該域名的根路徑和它的所有子路徑都有效。

用戶訪問網(wǎng)址www.example.com,果路徑設(shè)為/forums,那么這個(gè) Cookie 只有在訪問www.example.com/forums及其子路徑時(shí)才有效。以后,瀏覽器一旦訪問這個(gè)路徑,瀏覽器就會(huì)附上這段 Cookie 發(fā)送給服務(wù)器。

  • 瀏覽器的同源政策規(guī)定,兩個(gè)網(wǎng)址只要域名相同和端口相同,就可以共享 Cookie
  • 注意,這里不要求協(xié)議相同。
    也就是說,http://example.com設(shè)置的 Cookie,可以被https://example.com讀取。
  • 只要兩個(gè)網(wǎng)址的域名和端口號(hào)相同(協(xié)議可以不同),就可以共享cookie

瀏覽器可以設(shè)置不接受 Cookie,也可以設(shè)置不向服務(wù)器發(fā)送 Cookie。

  • 瀏覽器可以設(shè)置不接收cookie
  • 瀏覽器也可以設(shè)置不向服務(wù)器發(fā)送cookie

window.navigator.cookieEnabled屬性

  • window.navigator.cookieEnabled屬性返回一個(gè)布爾值,表示瀏覽器是否打開 Cookie 功能。
瀏覽器是否打開 Cookie 功能

window.navigator.cookieEnabled      // true

document.cookie屬性

  • document.cookie屬性返回當(dāng)前網(wǎng)頁(yè)的 Cookie。
當(dāng)前網(wǎng)頁(yè)的 Cookie

document.cookie



Cookie 由 HTTP 協(xié)議生成,也主要是供 HTTP 協(xié)議使用。

(1) HTTP 回應(yīng):Cookie 的生成

服務(wù)器如果希望在瀏覽器保存 Cookie,就要在 HTTP 回應(yīng)的頭信息里面,放置一個(gè)Set-Cookie字段。

  • 服務(wù)器在 http響應(yīng)頭 中放置 Set-Cookie 字段,就能在瀏覽器上保存cookie
  • HTTP 回應(yīng)可以包含多個(gè)Set-Cookie字段,即在瀏覽器生成多個(gè) Cookie
  • 除了 Cookie 的值,Set-Cookie字段還可以附加 Cookie 的屬性。
  • 一個(gè)Set-Cookie字段里面,可以同時(shí)包括多個(gè)屬性,沒有次序的要求。
  • 如果服務(wù)器想改變一個(gè)早先設(shè)置的 Cookie,必須同時(shí)滿足四個(gè)條件:Cookie 的key、domain、path和secure都匹配。
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco       ----------- 鍵值對(duì),cookie名:yummy_cookie, 值:choco
Set-Cookie: tasty_cookie=strawberry

[page content]
除了 Cookie 的值,Set-Cookie字段還可以附加 Cookie 的屬性


Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
一個(gè)Set-Cookie字段里面,可以同時(shí)包括多個(gè)屬性,沒有次序的要求。


Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
  • 如果服務(wù)器想改變一個(gè)早先設(shè)置的 Cookie,必須同時(shí)滿足四個(gè)條件:Cookie 的key、domain、path和secure都匹配。
    在key,domain,path,secure都相同時(shí),服務(wù)器才可以改變一個(gè)已經(jīng)設(shè)置的cookie,而不是新建一個(gè)同名cookie
    只要有一個(gè)屬性不同,就會(huì)生成一個(gè)全新的 Cookie,而不是替換掉原來那個(gè) Cookie。
Set-Cookie: key1=value1; domain=example.com; path=/blog

----------------------------服務(wù)器要改變?cè)缦仍O(shè)置的cookie,需要 key domain path secure都相同,如下

Set-Cookie: key1=value2; domain=example.com; path=/blog

(2) HTTP 請(qǐng)求:Cookie 的發(fā)送

瀏覽器向服務(wù)器發(fā)送 HTTP 請(qǐng)求時(shí),每個(gè)請(qǐng)求都會(huì)帶上相應(yīng)的 Cookie。也就是說,把服務(wù)器早前保存在瀏覽器的這段信息,再發(fā)回服務(wù)器。這時(shí)要使用 HTTP 頭信息的Cookie字段。

  • Cookie字段可以包含多個(gè) Cookie,使用分號(hào)(;)分隔。
Cookie: foo=bar
上面代碼會(huì)向服務(wù)器發(fā)送名為foo的 Cookie,值為bar。
  • Cookie字段可以包含多個(gè) Cookie,使用分號(hào)(;)分隔。
Cookie: name=value; name2=value2; name3=value3


例子:
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
  • 服務(wù)器收到瀏覽器發(fā)來的 Cookie 時(shí),有兩點(diǎn)是無法知道的。
    1. Cookie 的各種屬性,比如何時(shí)過期。
    2. 哪個(gè)域名設(shè)置的 Cookie,到底是一級(jí)域名設(shè)的,還是某一個(gè)二級(jí)域名設(shè)的。

(3) Cookie 的屬性

  • expires: 到期
  • 如果不設(shè)置expires屬性,或者設(shè)為null,Cookie 只在當(dāng)前會(huì)話(session)有效,瀏覽器窗口一旦關(guān)閉,當(dāng)前 Session 結(jié)束,該 Cookie 就會(huì)被刪除。
    另外,瀏覽器根據(jù)本地時(shí)間,決定 Cookie 是否過期,由于本地時(shí)間是不精確的,所以沒有辦法保證 Cookie 一定會(huì)在服務(wù)器指定的時(shí)間過期。
  • 如果同時(shí)指定了Expires和Max-Age,那么Max-Age的值將優(yōu)先生效。
  • 如果Set-Cookie字段沒有指定Expires或Max-Age屬性,那么這個(gè) Cookie 就是 Session Cookie,即它只在本次對(duì)話存在,一旦用戶關(guān)閉瀏覽器,瀏覽器就不會(huì)再保留這個(gè) Cookie。

Expires ------------------------ 到期時(shí)間,時(shí)間點(diǎn)

Expires屬性指定一個(gè)具體的到期時(shí)間,到了指定時(shí)間以后,瀏覽器就不再保留這個(gè) Cookie。它的值是 UTC 格式,可以使用Date.prototype.toUTCString()進(jìn)行格式轉(zhuǎn)換。

Max-Age ----------------------- 到期時(shí)間,時(shí)間段

Max-Age屬性指定從現(xiàn)在開始 Cookie 存在的秒數(shù)

Domain ------------------------- 域名

Domain屬性指定瀏覽器發(fā)出 HTTP 請(qǐng)求時(shí),哪些域名要附帶這個(gè) Cookie。
如果沒有指定該屬性,瀏覽器會(huì)默認(rèn)將其設(shè)為當(dāng)前 URL 的一級(jí)域名,
比如www.example.com會(huì)設(shè)為example.com,而且以后如果訪問example.com的任何子域名,HTTP 請(qǐng)求也會(huì)帶上這個(gè) Cookie。
如果服務(wù)器在Set-Cookie字段指定的域名,不屬于當(dāng)前域名,瀏覽器會(huì)拒絕這個(gè) Cookie。

Path ----------------------------- 路徑

Path屬性指定瀏覽器發(fā)出 HTTP 請(qǐng)求時(shí),哪些路徑要附帶這個(gè) Cookie。

  • 只要瀏覽器發(fā)現(xiàn),Path屬性是 HTTP 請(qǐng)求路徑的開頭一部分,就會(huì)在頭信息里面帶上這個(gè) Cookie。比如,PATH屬性是/,那么請(qǐng)求/docs路徑也會(huì)包含該 Cookie。當(dāng)然,前提是域名必須一致。

Secure --------------- 在https協(xié)議時(shí),發(fā)送cookie

Secure屬性指定瀏覽器只有在加密協(xié)議 HTTPS 下,才能將這個(gè) Cookie 發(fā)送到服務(wù)器。

  • secure:是安全的意思
  • 另一方面,如果當(dāng)前協(xié)議是 HTTP,瀏覽器會(huì)自動(dòng)忽略服務(wù)器發(fā)來的Secure屬性。-
  • 該屬性只是一個(gè)開關(guān),不需要指定值。如果通信是 HTTPS 協(xié)議,該開關(guān)自動(dòng)打開。

HttpOnly ------------- 指定cookie無法通過腳本拿到

HttpOnly屬性指定該 Cookie 無法通過 JavaScript 腳本拿到,主要是Document.cookie屬性、XMLHttpRequest對(duì)象和 Request API 都拿不到該屬性。這樣就防止了該 Cookie 被腳本讀到,只有瀏覽器發(fā)出 HTTP 請(qǐng)求時(shí),才會(huì)帶上該 Cookie。

  • document.cookie屬性
  • XMLHttpRequest對(duì)象
  • Request API
    如何回應(yīng)頭設(shè)置HttpOnly,三個(gè)都拿不到cookie

document.cookie --------- 讀寫當(dāng)前網(wǎng)頁(yè)cookie

讀出全部cookie,寫入一個(gè)cookie

document.cookie屬性用于讀寫當(dāng)前網(wǎng)頁(yè)的 Cookie
document.cookie屬性是可寫的,可以通過它為當(dāng)前網(wǎng)站添加 Cookie。

  • 讀取的時(shí)候,它會(huì)返回當(dāng)前網(wǎng)頁(yè)的所有 Cookie,前提是該 Cookie 不能有HTTPOnly屬性,它們之間使用分號(hào)分隔。
  • 寫入的時(shí)候,Cookie 的值必須寫成key=value的形式。注意( 值的 )等號(hào)兩邊不能有空格。
  • 另外,寫入 Cookie 的時(shí)候,必須對(duì)分號(hào)、逗號(hào)和空格進(jìn)行轉(zhuǎn)義(它們都不允許作為 Cookie 的值),這可以用encodeURIComponent方法達(dá)到。
  • 寫入 Cookie 的時(shí)候,可以一起寫入 Cookie 的屬性。
  • document.cookie一次只能寫入一個(gè) Cookie,而且寫入并不是覆蓋,而是添加。
  • document.cookie讀寫行為的差異(一次可以讀出全部 Cookie,但是只能寫入一個(gè) Cookie )

document.cookie = 'test1=hello';     ------- 值中的 = 之間不能有空格
document.cookie = 'test2=world';     ------- 寫cookie時(shí),只能一個(gè)個(gè)寫入
document.cookie                      ------- 讀cookie時(shí),讀取所有cookie

// test1=hello;test2=world
  • document.cookie讀寫行為的差異(一次可以讀出全部 Cookie,但是只能寫入一個(gè) Cookie),與 HTTP 協(xié)議的 Cookie 通信格式有關(guān)。
  • 瀏覽器向服務(wù)器發(fā)送 Cookie 的時(shí)候,Cookie字段是使用一行將所有 Cookie 全部發(fā)送;
  • 服務(wù)器向?yàn)g覽器設(shè)置 Cookie 的時(shí)候,Set-Cookie字段是一行設(shè)置一個(gè) Cookie。

屬性的寫入注意點(diǎn):

  • path屬性必須為絕對(duì)路徑,默認(rèn)為當(dāng)前路徑。
  • domain屬性值必須是當(dāng)前發(fā)送 Cookie 的域名的一部分。比如,當(dāng)前域名是example.com,就不能將其設(shè)為foo.com。該屬性默認(rèn)為當(dāng)前的一級(jí)域名(不含二級(jí)域名)。
  • max-age屬性的值為秒數(shù)。
  • expires屬性的值為 UTC 格式,可以使用Date.prototype.toUTCString()進(jìn)行日期格式轉(zhuǎn)換。

Cookie 的屬性一旦設(shè)置完成,就沒有辦法讀取這些屬性的值。

刪除一個(gè)現(xiàn)存 Cookie 的唯一方法,是設(shè)置它的expires屬性為一個(gè)過去的日期。

document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';


上面代碼中,名為fontSize的 Cookie 的值為空,過期時(shí)間設(shè)為1970年1月1月零點(diǎn),就等同于刪除了這個(gè) Cookie。







async函數(shù)

async函數(shù)是generator函數(shù)的語法糖。async函數(shù)就是將 Generator 函數(shù)的星號(hào)(*)替換成async,將yield替換成await,僅此而已。

  • async:是異步的意思

  • async函數(shù)對(duì) Generator 函數(shù)的改進(jìn),體現(xiàn)在以下四點(diǎn)。

(1) 內(nèi)置執(zhí)行器

Generator 函數(shù)的執(zhí)行必須靠執(zhí)行器,所以才有了co模塊,而async函數(shù)自帶執(zhí)行器。也就是說,async函數(shù)的執(zhí)行,與普通函數(shù)一模一樣,只要一行。

  • async函數(shù)自帶執(zhí)行器,和普通函數(shù)一樣的方法調(diào)用

(2) 更好的語義

async和await,比起星號(hào)和yield,語義更清楚了。async表示函數(shù)里有異步操作,await表示緊跟在后面的表達(dá)式需要等待結(jié)果。

  • async 表示函數(shù)中有異步操作
  • await 表示緊跟在await后面的表達(dá)式需要等待結(jié)果

(3) 更廣的適用性

co模塊約定,yield命令后面只能是 Thunk 函數(shù)或 Promise 對(duì)象,而async函數(shù)的await命令后面,可以是 Promise 對(duì)象和原始類型的值(數(shù)值、字符串和布爾值,但這時(shí)等同于同步操作)。

  • await命令后面,可以是Promise對(duì)象,和原始類型的值

(4) 返回值是 Promise -------------------------- ( 重要 )

async函數(shù)的返回值是 Promise 對(duì)象,這比 Generator 函數(shù)的返回值是 Iterator 對(duì)象方便多了。你可以用then方法指定下一步的操作。
進(jìn)一步說,async函數(shù)完全可以看作多個(gè)異步操作,包裝成的一個(gè) Promise 對(duì)象,而await命令就是內(nèi)部then命令的語法糖。

  • async函數(shù)返回的是promise對(duì)象,可以使用 then 方法指定下一步操作

基本用法:

async函數(shù)返回一個(gè) Promise 對(duì)象,可以使用then方法添加回調(diào)函數(shù)。當(dāng)函數(shù)執(zhí)行的時(shí)候,一旦遇到await就會(huì)先返回,等到異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語句。

  • async返回的是promise對(duì)象,async函數(shù)內(nèi)部return語句返回的值,會(huì)成為then方法回調(diào)函數(shù)的參數(shù)。
async function f() {
  return 'hello world';   ------- 在async函數(shù)中,return語句返回的值,會(huì)作為 then方法回調(diào)函數(shù)的參數(shù)
}

f().then(v => console.log(v))
// "hello world"


上面代碼中,函數(shù)f內(nèi)部return命令返回的值,會(huì)被then方法回調(diào)函數(shù)接收到。

Promise 對(duì)象的狀態(tài)變化

async函數(shù)返回的 Promise 對(duì)象,必須等到內(nèi)部所有await命令后面的 Promise 對(duì)象執(zhí)行完,才會(huì)發(fā)生狀態(tài)改變,除非遇到return語句或者拋出錯(cuò)誤。也就是說,只有async函數(shù)內(nèi)部的異步操作執(zhí)行完,才會(huì)執(zhí)行then方法指定的回調(diào)函數(shù)。

  • async函數(shù)返回的promise對(duì)象,必須等到所有await后的promise對(duì)象執(zhí)行完,才會(huì)發(fā)生狀態(tài)改變
    即:只有async函數(shù)內(nèi)部的異步操作執(zhí)行完,才會(huì)執(zhí)行then方法指定的回調(diào)函數(shù) ----------------------- ( 重要 )
async function getTitle(url) {
  let response = await fetch(url);
  let html = await response.text();
  return html.match(/<title>([\s\S]+)<\/title>/i)[1];
}
getTitle('https://tc39.github.io/ecma262/').then(console.log)
// "ECMAScript 2017 Language Specification"


上面代碼中,函數(shù)getTitle內(nèi)部有三個(gè)操作:抓取網(wǎng)頁(yè)、取出文本、匹配頁(yè)面標(biāo)題。

只有這三個(gè)操作全部完成,才會(huì)執(zhí)行then方法里面的console.log。

await 命令

正常情況下,await命令后面是一個(gè) Promise 對(duì)象。
如果不是,會(huì)被轉(zhuǎn)成一個(gè)立即resolve的 Promise 對(duì)象。

  • await命令后面的 Promise 對(duì)象如果變?yōu)閞eject狀態(tài),則reject的參數(shù)會(huì)被catch方法的回調(diào)函數(shù)接收到。
async function f() {
  return await 123;
}

f().then(v => console.log(v))
// 123

上面代碼中,await命令的參數(shù)是數(shù)值123,它被轉(zhuǎn)成 Promise 對(duì)象,并立即resolve

  • 只要一個(gè)await語句后面的 Promise 變?yōu)閞eject,那么整個(gè)async函數(shù)都會(huì)中斷執(zhí)行。
async function f() {
  await Promise.reject('出錯(cuò)了');
  await Promise.resolve('hello world'); // 不會(huì)執(zhí)行
}


上面代碼中,第二個(gè)await語句是不會(huì)執(zhí)行的,因?yàn)榈谝粋€(gè)await語句狀態(tài)變成了reject。

  • 有時(shí),我們希望即使前一個(gè)異步操作失敗,也不要中斷后面的異步操作。
    這時(shí)可以將第一個(gè)await放在try...catch結(jié)構(gòu)里面,這樣不管這個(gè)異步操作是否成功,第二個(gè)await都會(huì)執(zhí)行。
async function f() {
  try {
    await Promise.reject('出錯(cuò)了');
  } catch(e) {
  }
  return await Promise.resolve('hello world');
}

f()
.then(v => console.log(v))
// hello world

實(shí)例:

import React from 'react';


export default class Func extends React.Component {
    componentDidMount() {
        async function getName() {
            let i = 0;
            setInterval(() => {
                i = i+1;
                console.log(i)
            }, 1000);          // 每秒輸出1,2,3,4,5...
            const a = await new Promise(resolve => setTimeout(() => resolve(22222), 2000));
            console.log(a);    // 2秒后輸出22222
            const b = await new Promise(resolve => setTimeout(() => resolve(1), 2000)); 
            console.log(b)     // 再過兩秒輸出 1
            const c =  await new Promise(resolve => setTimeout(() => resolve(a+b), 2000)); 
            return c;
        };
        getName().then(res => console.log(res, 'res'))    // 一共6秒后輸出 22223
    }
    render() {
        return ( 
            <div> function scope test </div>
        );
    }
}

      --------------------------   異步方法同步執(zhí)行   -------------------------、
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容