如何讀取 Cookie ?
栏目: JavaScript · 发布时间: 5年前
内容简介:當我們使用VS Code 1.34.0Quokka 1.0.216
當我們使用 document.cookie()
讀取 Cookie 時,回傳為 String,我們希望提供 Key 讀取其 Value,這常見的需求該如何實現呢 ? 本文分別使用 Imperative、Functional 與 Maybe 三種方式實現。
Version
VS Code 1.34.0
Quokka 1.0.216
Ramda 0.26.1
Cookie
let readCookie = () => { let data = document.cookie.split('; ').slice(0, -2); console.log(getCookie('firstName')(data)); };
實務上要使用 document.cookie
去讀取 cookie,但讀出來為以下格式:
firstName=Sam; lastName=Xiao; _ga=GA1.1.320322304.1546312556; Hm_lvt_47acec2d282c3986f1b600abdc11c7ab=155525178
倒數第二個 ;
之後的資訊並不是我們要的,所以先 split()
成 array 後,用 slice()
取得不含倒數兩個 element 的新 array,最後再傳入 getCookie()
,根據 key 取得 value。
Imperative
let data = [ 'firstName=Sam', 'lastName=Xiao' ]; // getCookie :: String -> [String] -> String let getCookie = key => arr => { for(let i = 0; i < arr.length; i++) { let tuple = arr[i].split('='); if (tuple[0] === key) return tuple[1]; } return ''; }; console.log(getCookie('firstName')(data)); console.log(getCookie('lastName')(data)); console.log(getCookie('age')(data));
data
為根據 document.cookie()
所整理過的 string。
我們希望當傳入 key 時, getCookie()
回傳 value。
第 8 行
for(let i = 0; i < arr.length; i++) {
Imperative 會使用 for
loop 一個一個找。
第 9 行
let tuple = s.split('=');
Array 中的 string 形式為 firstName=Sam
,可再使用 split()
拆成 array,因為很類似 tuple,變數姑且命名為 tuple
。
tuple
當然是很糟糕的命名,應該取一個有意義的變數名稱
第 10 行
if (tuple[0] === key) return tuple[1];
tuple[0]
即為 key,而 tuple[1]
為 value,因此可直接使用 if
判斷。
Imperative 會充斥著 中繼變數
,然後就開始為 變數命名
傷腦筋,要如何使變數可讀性高又有意義,但畢竟我們在乎的是結果,這些中繼變數真的需要嗎 ? 是值得深思的問題
13 行
return '';
若傳入的 key 不存在,則回傳 empty string,避免產生 undefined
。
Functional
import { pipe, compose, split, converge, nth, objOf, map, find, propOr, prop, isNil, complement } from 'ramda'; let data = [ 'firstName=Sam', 'lastName=Xiao' ]; // strToObj :: String -> Object let strToObj = pipe( split('='), converge(objOf, [nth(0), nth(1)]) ); // isNotNil :: * -> Boolean let isNotNil = complement(isNil); // getCookie :: String -> [String] -> String let getCookie = key => pipe( map(strToObj), find(compose(isNotNil, prop(key))), propOr('', key) ); console.log(getCookie('firstName')(data)); console.log(getCookie('lastName')(data)); console.log(getCookie('age')(data));
17 行
// getCookie :: String -> [String] -> String let getCookie = key => pipe( map(strToObj), find(compose(isNotNil, prop(key))), propOr('', key) );
FP 不會使用 for
loop 處理,可由 pipe()
清楚看出演算法流程:
- 先使用
map()
將 array 內的 string 轉成 object - 再使用
find()
搜尋 array 中每個 object,找到就傳回 object,否則傳回undefined
- 最後使用
propOr()
根據 key 取得 value
其中將 string 轉成 object,是想借助 Ramda 對 object 支援豐富 function。
可以看出 FP 解決問題方式是將問題最小化切割,然後各個擊破,與 Imperative整體思考方式不同
第 8 行
// strToObj :: String -> Object let strToObj = pipe( split('='), converge(objOf, [nth(0), nth(1)]) );
split() objOf()
20 行
find(compose(isNotNil, prop(key)))
使用 find()
根據 key 找尋 value,其 predicate 為 (a -> Boolean)
,而 prop()
回傳為 a | Undefined
,因此組合 isNotNil()
使其轉成 boolean。
14 行
// isNotNil :: * -> Boolean let isNotNil = complement(isNil);
Ramda 並沒有提供 isNotNil()
,須自行組合,也可使用 compose(not, isNil)
。
21 行
propOr('', key)
由於 find()
可能回傳 undefined
,所以特別使用了 propOr()
處理。
我們可發現 FP 完全 沒有
中繼變數,所以再也不必為了變數命名而傷透腦筋
Maybe
import { pipe, compose, split, converge, nth, objOf, map, find, prop, isNil, complement } from 'ramda'; import { prop as prop_ } from 'crocks'; let data = [ 'firstName=Sam', 'lastName=Xiao' ]; // strToObj :: String -> Object let strToObj = pipe( split('='), converge(objOf, [nth(0), nth(1)]) ); // isNotNil :: * -> Boolean let isNotNil = complement(isNil); // getCookie :: String -> [String] -> Maybe String let getCookie = key => pipe( map(strToObj), find(compose(isNotNil, prop(key))), prop_(key), ); console.log(getCookie('firstName')(data).option('N/A')); console.log(getCookie('lastName')(data).option('N/A')); console.log(getCookie('age')(data).option('N/A'));
Ramda 的 find()
唯一缺點就是回傳 undefined
,因此我們必須小心翼翼地使用 propOr()
處理,但這有幾個缺點:
-
undefined
並非邏輯的一部分,是為了find()
而處理 - 若一不小心使用了
prop()
,就可能回傳undefined
- 目前我們使用
propOr('', key)
,也就是undefined
時回傳 empty string,但若使用端想自行決定undefined
的 string 呢 ?
比較好的方式是回傳 Maybe
,由使用端決定 undefined
該如何處理。
21 行
find(compose(isNotNil, prop(key))), prop_(key),
由於要回傳 Maybe
,改用 Crocks 的 prop()
,而不是 Ramd 的 prop()
,因為 Crocks 很多 function 名稱與 Ramda 一樣,差異只在於回傳 Maybe
,因此 Crocks 所提供的同名 function 一律以 _
postfix 表示。
26 行
console.log(getCookie('firstName')(data).option('N/A')); console.log(getCookie('lastName')(data).option('N/A')); console.log(getCookie('age')(data).option('N/A'));
由於 getCookie()
回傳 Maybe
,必須透過 option()
將 Maybe
轉回 string。
若 undefined
時想顯示 N/A
,可一併傳進 option()
。
使用 Maybe
後, undefined
改由使用端處理, getCookie()
可專心處理正常邏輯,不必再為了 undefined
分心,程式碼邏輯也更清楚
以上所述就是小编给大家介绍的《如何讀取 Cookie ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。