Lưu dữ liệu trên trình duyệt với LocalStorage, sessonStorage
Trong các ứng dụng web, dữ liệu thường được lưu tại các cơ sở dữ liệu được tổ chức bài bản như MySQL, MongoDB, PostgresQL, v/v. Tuy nhiên, trong một vài trường hợp, dữ liệu không cần lưu giữ dài hạn tại một cơ sở dữ liệu và có thể được giữ trực tiếp ngay trên trình duyệt của người dùng. Để lưu trữ dữ liệu trên trình duyệt, ta có thể dùng một trong hai API chính của browser: localStorage
và sessionStorage
.
Cả hai tính năng trên hoạt động khá tương đồng, dữ liệu được lưu dưới dạng các cặp key/value
. Các thông tin được lưu trữ trên sessionStorage
có thể tồn tại sau khi tải lại trang (page refresh), trong khi đối với localStorage
, dữ liệu sẽ được giữ lại ngay cả khi tắt và mở lại trình duyệt (browser restart).
localStorage
và sessionStorage
đều có các methods và thuộc tính tương tự nhau:
setItem(key, value)
– ghi các cặp key/value và bộ nhớgetItem(key)
– truy xuất dữ liệu bằng keyremoveItem(key)
– xoákey/value
trên bộ nhớclear()
– xoá toàn bộkey(index)
– lấy một key dựa trên thứ tựlength
– số lượng giá trị đang được lưu
Có thể thấy rằng, localStorage
và sessionStorage
có cấu trúc dạng Map
với setItem/getItem/removeItem
và cũng có thể truy xuất dữ liệu bằng index
với key(index)
.
Sử dụng localStorage
Đặc điểm chính của localStorage
là:
- Dữ liệu có thể được truy cập từ nhiều tabs khác nhau của cùng một domain (origin)
- Các dữ liệu được lưu là không có thời hạn. Dữ liệu vẫn tồn tại sau khi khởi động lại trình duyệt hoặc khởi đồng lại máy tính.
Để hiểu rõ hơn, chạy đoạn code sau:
localStorage.setItem('test', 1);
Sau đó, đóng và mở lại trình duyệt, hoặc tải trang trên một tab khác và chạy đoạn code sau:
alert( localStorage.getItem('test') ); // Kết quả: 1
Lưu ý, dữ liệu sẽ được chia sẻ trên các tabs có cùng origin (domain/port/protocol), phần đường dẫn phía sau có thể khác nhau. Vì dữ liệu được chia sẻ qua các tabs, khi ta ghi dữ liệu trên một tab, các tabs khác cũng sẽ thấy được sự thay đổi.
Object-like access
Ngoài cách sử dụng method setItem/getItem/removeItem
, ta còn có thể truy xuất dữ liệu được lưu trữ trên localStorage
như một object thông thường:
// set key
localStorage.test = 2;
// get key
alert( localStorage.test ); // Kết quả: 2
// remove key
delete localStorage.test;
Khi sử dụng các này để làm việc với localStorage
, ta cần lưu ý các điểm sau:
- Một số key như
length
haytoString
là các method sẵn có củalocalStorage
, nếu dùng theo dạng object, có thể ta sẽ gặp lỗi. Nhưng nếu dùng vớisetItem/getItem
thì sẽ không có vấn đề gì nghiêm trọng:
let key = 'length';
localStorage[key] = 5; // Error, không thể gán length cho localStorage
- Ngoài ra, mỗi khi dữ liệu trên
localStorage
thay đổi, trình duyệt sẽ kích hoạtstorage
event. Các event này sẽ không được kích hoạt nếu là dùng theo dạng object.
Vòng lặp trên các keys
Ta có thể setItem/getItem/removeItem
với localStorage
để xem hoặc ghi thông tin cho từng key. Làm cách nào để xem tất cả dữ liệu đang được lưu trên localStorage
?
Ta có thể thực hiện bằng cách dùng vòng lặp trên tất cả các key của localStorage
(vì localStorage
không cung cấp tính năng lặp trực tiếp trên các dữ liệu được lưu):
for(let i=0; i<localStorage.length; i++) {
let key = localStorage.key(i);
alert(`${key}: ${localStorage.getItem(key)}`);
}
Hoặc sử dụng cú pháp for key in localStorage
(cách này sẽ hiển thị cả những method sẵn có của localStorage
như getItem/setItem
:
for(let key in localStorage) {
alert(key); // có cả getItem, setItem và các key sẵn có khác
}
Để loại các thuộc tính và method sẵn có, ta dùng hasOwnProperty
:
for(let key in localStorage) {
if (!localStorage.hasOwnProperty(key)) {
continue; // loại các key "setItem", "getItem", v/v
}
alert(`${key}: ${localStorage.getItem(key)}`);
}
Các ngắn gọn hơn, ta dùng Object.keys
để lặp qua các key của localStorage
(các method và thuộc tính sẵn có sẽ không được hiển thị):
let keys = Object.keys(localStorage);
for(let key of keys) {
alert(`${key}: ${localStorage.getItem(key)}`);
}
Lưu các dạng dữ liệu khác trên localStorage
Có một điều lưu ý, tất cả dữ liệu được lưu trữ trên localStorage
đều có dạng string
. Nếu ta cố gắng lưu các dạng dữ liệu khác, nó sẽ được chuyển đổi sang dạng string
một cách tự động:
localStorage.user = {name: "John"};
alert(localStorage.user); // [object Object]
Để giải quyết vấn đề này, ta có thể dùng JSON
để lưu các dạng dữ liệu object
:
localStorage.user = {name: "John"};
alert(localStorage.user); // [object Object]
Ta có thể thực hiện bằng cách dùng vòng lặp trên tất cả các key của localStorage
(vì localStorage
không cung cấp tính năng lặp trực tiếp trên các dữ liệu được lưu):
localStorage.user = JSON.stringify({name: "John"});
// sometime later
let user = JSON.parse( localStorage.user );
alert( user.name ); // John
sessionStorage
sessionStorage
có các thuộc tính và method tương đương như localStorage
với một số điểm hạn chế:
sessionStorage
chỉ tồn tại trên tab hiện tại:- Các tabs khác của cùng origin sẽ có
sessionStorage
riêng - Nếu trên một tabs có sử dụng
iframe
cho cùng một origin,sessionStorage
sẽ được chia sẻ.
- Các tabs khác của cùng origin sẽ có
- Dữ liệu có thể tồn tại sau khi tải lại trang, nhưng sẽ mất nếu đóng tab.
Vì các điểm hạn chế như trên, sessionStorage
thường ít được sử dụng hơn localStorage
. Để xem thử cách hoạt động của sessionStorage
, chạy đoạn code sau:
sessionStorage.setItem('test', 1);
Sau đó, tải lại trang và chạy đoạn code sau:
alert( sessionStorage.getItem('test') ); // Sau khi tải lại trang: 1
Nếu bạn chạy đoạn code ngay trên trong một tab khác, giá trị nhận được sẽ là null
.
Storage event
Khi dữ liệu trên localStorage
hoặc sessionStrorage
được cập nhật, storage event
sẽ được kích hoạt với các thuộc tính sau:
key
– key đươc cập nhật (null
nếu.clear()
được dùng)oldValue
– giá trị cũ (null
nếu key mới được được tạo)newValue
– giá trị mới (null
nếu key bị xoá)url
– đường dẫn của trang tại nơi sự thay đổi diễn rastorageArea
–localStorage
hoặcsessionStorage
Một lưu ý quan trọng: event chỉ được kích hoạt tại các tabs có thể truy cập vào storage (cùng origin) trừ tab nơi sự thay đổi diễn ra.
Ví dụ, ta có hai tabs chạy cùng một trang web. localStorage
sẽ được chia sẻ giữa hai tab trên. Nếu cả hai tab đề được cài đặt để đợi event window.onstorage
, mỗi tab sẽ chỉ nhận được event khi sự thay đổi diễn ra tại tab còn lại.
Để hiểu vấn đề này, bạn có thể chạy đoạn code sau trên hai tabs khác nhau với cùng một trang web:
window.onstorage = event => {
if (event.key != 'now') return;
alert(event.key + ':' + event.newValue + " at " + event.url);
};
localStorage.setItem('now', Date.now());
event.url
là đường dẫn tại trang mà sự thay đổi diễn ra. Với tính năng storage event
này, ta có thể tạo ra sự giao tiếp giữa các tabs của cùng một trang web trên trình duyệt.
Tạm kết
localStorage
và sessionStorage
có phép lưu trữ dữ liệu dưới dạng các cặp key/value
trên trình duyệt:
- Cả
key
vàvalue
đều phải có dạngstring
- Kích thước không quá 5MB, tuỳ vào trình duyệt
- Không có thời hạn
- Dữ liệu được chia sẻ trên các tabs có cùng origin (domain/port/protocol)
Điểm khác nhau:
localStorage
:- Chia sẽ giữa các tabs và của sổ có cùng origin
- Tồn tại ngay cả sau khi khởi động lại trình duyệt
sessionStorage
:- Chỉ tồn tại trên một tab, bao gồm
iframe
trong tab đó với cùng origin - Có thể tồn tại sau khi tải lại trang
- Chỉ tồn tại trên một tab, bao gồm
API:
setItem(key, value)
– ghi các cặp key/value và bộ nhớgetItem(key)
– truy xuất dữ liệu bằng keyremoveItem(key)
– xoákey/value
trên bộ nhớclear()
– xoá toàn bộkey(index)
– lấy một key dựa trên thứ tựlength
– số lượng giá trị đang được lưu- Dùng
Object.keys
để xem tất cảkey
đã lưu - Có thể cập nhật dữ liệu theo dạng object với key, trong trường hợp này event sẽ không được kích hoạt
Storage event:
- Kích hoạt khi các method sau được gọi:
setItem
,removeItem
vàclear()
- Chứa các thông tin về tác vụ được thực hiện (
key/oldValue/newValue
), đường dẫn của taburl
vàstorageArea
(localStorage
hoặcsessionStorage
) - Được kích hoạt tại tất cả tabs và của sổ được chia sẻ storage, trừ tab nơi sự thay đổi diễn ra.
Tags In
Related Posts
Leave a Reply Cancel reply
Categories
- Bài viết (1)
- Blog (24)
- Code Review (3)
- Course Introduction (2)
- CSS (4)
- CSS Grid (4)
- Javascript (2)
- Lesson (11)
- Lưu dữ liệu trên trình duyệt (1)
- Network Requests (1)
- OneDirect Projects (1)
- Product Review (3)
- Stage Content (16)
- WCS Courses Content (17)