Skip to content

feat: removeItem when storing null or undefined #93

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ It was time to do a full review and refactoring, which results in:
- `indexedDB` database and object store names default values are exported and can be changed
(see the [interoperability guide](./docs/INTEROPERABILITY.md))
- `indexedDB` storage will now works in web workers too
- When trying to store `null` or `undefined`, `removeItem()` instead of just bypassing (meaning the old value was kept)

### Breaking changes

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ this.localStorage.setItem('user', user).subscribe(() => {});

You can store any value, without worrying about stringifying.

Storing `null` or `undefined` can cause issues in some browsers, so the item will be removed instead.

### Deleting data

To delete one item:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,9 @@ export class IndexedDBDatabase implements LocalDatabase {
*/
setItem(key: string, data: any): Observable<boolean> {

/* Storing `null` or `undefined` is known to cause issues in some browsers.
* So it's useless, not storing anything in this case */
/* Storing `undefined` or `null` in `localStorage` can cause issues in some browsers so removing item instead */
if ((data === undefined) || (data === null)) {

/* Trigger success */
return of(true);

return this.removeItem(key);
}

/* Open a transaction in write mode */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,25 +77,25 @@ export class LocalStorageDatabase implements LocalDatabase {
*/
setItem(key: string, data: any): Observable<boolean> {

/* Storing `undefined` or `null` in `localStorage` can cause issues in some browsers and has no sense */
if ((data !== undefined) && (data !== null)) {

let serializedData: string | null = null;
/* Storing `undefined` or `null` in `localStorage` can cause issues in some browsers so removing item instead */
if ((data === undefined) || (data === null)) {
return this.removeItem(key);
}

/* Try to stringify (can fail on circular references) */
try {
serializedData = JSON.stringify(data);
} catch (error) {
return throwError(error as TypeError);
}
let serializedData: string | null = null;

/* Can fail if storage quota is exceeded */
try {
localStorage.setItem(this.prefixKey(key), serializedData);
} catch (error) {
return throwError(error as DOMException);
}
/* Try to stringify (can fail on circular references) */
try {
serializedData = JSON.stringify(data);
} catch (error) {
return throwError(error as TypeError);
}

/* Can fail if storage quota is exceeded */
try {
localStorage.setItem(this.prefixKey(key), serializedData);
} catch (error) {
return throwError(error as DOMException);
}

/* Wrap in a RxJS `Observable` to be consistent with other storages */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ export class MemoryDatabase implements LocalDatabase {
*/
setItem(key: string, data: any): Observable<boolean> {

/* Storing `undefined` or `null` in `localStorage` is useless */
if ((data !== undefined) && (data !== null)) {

this.memoryStorage.set(key, data);

/* Storing `undefined` or `null` in `localStorage` is useless, so removing item instead */
if ((data === undefined) || (data === null)) {
return this.removeItem(key);
}

this.memoryStorage.set(key, data);

/* Wrap in a RxJS `Observable` to be consistent with other storages */
return of(true);

Expand Down
14 changes: 6 additions & 8 deletions projects/ngx-pwa/local-storage/src/lib/lib.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,9 @@ function tests(description: string, localStorageServiceFactory: () => LocalStora

it('null', (done) => {

const value = null;

localStorageService.setItem(key, value).pipe(
mergeMap(() => localStorageService.getItem(key))
localStorageService.setItem(key, 'test').pipe(
mergeMap(() => localStorageService.setItem(key, null)),
mergeMap(() => localStorageService.getItem(key)),
).subscribe((result) => {

expect(result).toBeNull();
Expand All @@ -181,10 +180,9 @@ function tests(description: string, localStorageServiceFactory: () => LocalStora

it('undefined', (done) => {

const value = undefined;

localStorageService.setItem(key, value).pipe(
mergeMap(() => localStorageService.getItem(key))
localStorageService.setItem(key, 'test').pipe(
mergeMap(() => localStorageService.setItem(key, undefined)),
mergeMap(() => localStorageService.getItem(key)),
).subscribe((result) => {

expect(result).toBeNull();
Expand Down