如何讀取 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

如何讀取 Cookie ?

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() 清楚看出演算法流程:

  1. 先使用 map() 將 array 內的 string 轉成 object
  2. 再使用 find() 搜尋 array 中每個 object,找到就傳回 object,否則傳回 undefined
  3. 最後使用 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 完全 沒有 中繼變數,所以再也不必為了變數命名而傷透腦筋

如何讀取 Cookie ?

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 ?


以上所述就是小编给大家介绍的《如何讀取 Cookie ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

智能商业

智能商业

曾鸣 / 中信出版集团 / 2018-11 / 68.00

《智能商业》由马云作序推荐。《智能商业》是阿里巴巴集团前总参谋长曾鸣,对互联网时代的重要趋势做出革命性解读的作品,披露了其对于未来商业模式的思考和判断。 2006年,曾鸣教授加入阿里巴巴集团,参与阿里巴巴集团及各重要业务线,如淘宝、支付宝、阿里云计算、菜鸟等的发展,被业界称为阿里的“军师”。 基于在阿里巴巴集团十几年的实践经验,以及对互联网、大数据和人工智能的深入思考,曾鸣教授在《智能......一起来看看 《智能商业》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具