Skip to content
This repository was archived by the owner on Dec 26, 2025. It is now read-only.

Commit 5b9947f

Browse files
authored
Add CancellationToken support to Async methods (#146)
1 parent 050cb65 commit 5b9947f

5 files changed

Lines changed: 120 additions & 87 deletions

File tree

src/Blazored.LocalStorage/BrowserStorageProvider.cs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using Microsoft.JSInterop;
1+
using Microsoft.JSInterop;
22
using System;
3+
using System.Threading;
34
using System.Threading.Tasks;
45

56
namespace Blazored.LocalStorage
@@ -15,26 +16,26 @@ public BrowserStorageProvider(IJSRuntime jSRuntime)
1516
_jSInProcessRuntime = jSRuntime as IJSInProcessRuntime;
1617
}
1718

18-
public ValueTask ClearAsync()
19-
=> _jSRuntime.InvokeVoidAsync("localStorage.clear");
19+
public ValueTask ClearAsync(CancellationToken? cancellationToken = null)
20+
=> _jSRuntime.InvokeVoidAsync("localStorage.clear", cancellationToken ?? CancellationToken.None);
2021

21-
public ValueTask<string> GetItemAsync(string key)
22-
=> _jSRuntime.InvokeAsync<string>("localStorage.getItem", key);
22+
public ValueTask<string> GetItemAsync(string key, CancellationToken? cancellationToken = null)
23+
=> _jSRuntime.InvokeAsync<string>("localStorage.getItem", cancellationToken ?? CancellationToken.None, key);
2324

24-
public ValueTask<string> KeyAsync(int index)
25-
=> _jSRuntime.InvokeAsync<string>("localStorage.key", index);
25+
public ValueTask<string> KeyAsync(int index, CancellationToken? cancellationToken = null)
26+
=> _jSRuntime.InvokeAsync<string>("localStorage.key", cancellationToken ?? CancellationToken.None, index);
2627

27-
public ValueTask<bool> ContainKeyAsync(string key)
28-
=> _jSRuntime.InvokeAsync<bool>("localStorage.hasOwnProperty", key);
28+
public ValueTask<bool> ContainKeyAsync(string key, CancellationToken? cancellationToken = null)
29+
=> _jSRuntime.InvokeAsync<bool>("localStorage.hasOwnProperty", cancellationToken ?? CancellationToken.None, key);
2930

30-
public ValueTask<int> LengthAsync()
31-
=> _jSRuntime.InvokeAsync<int>("eval", "localStorage.length");
31+
public ValueTask<int> LengthAsync(CancellationToken? cancellationToken = null)
32+
=> _jSRuntime.InvokeAsync<int>("eval", cancellationToken ?? CancellationToken.None, "localStorage.length");
3233

33-
public ValueTask RemoveItemAsync(string key)
34-
=> _jSRuntime.InvokeVoidAsync("localStorage.removeItem", key);
34+
public ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null)
35+
=> _jSRuntime.InvokeVoidAsync("localStorage.removeItem", cancellationToken ?? CancellationToken.None, key);
3536

36-
public ValueTask SetItemAsync(string key, string data)
37-
=> _jSRuntime.InvokeVoidAsync("localStorage.setItem", key, data);
37+
public ValueTask SetItemAsync(string key, string data, CancellationToken? cancellationToken = null)
38+
=> _jSRuntime.InvokeVoidAsync("localStorage.setItem", cancellationToken ?? CancellationToken.None, key, data);
3839

3940
public void Clear()
4041
{

src/Blazored.LocalStorage/ILocalStorageService.cs

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,102 @@
11
using System;
2+
using System.Threading;
23
using System.Threading.Tasks;
34

45
namespace Blazored.LocalStorage
56
{
67
public interface ILocalStorageService
78
{
8-
/// <summary>
9-
/// Clears all data from local storage.
9+
/// <summary>
10+
/// Clears all data from local storage.
1011
/// </summary>
1112
/// <returns>A <see cref="ValueTask"/> representing the completion of the operation.</returns>
12-
ValueTask ClearAsync();
13+
ValueTask ClearAsync(CancellationToken? cancellationToken = null);
1314

14-
/// <summary>
15-
/// Retrieve the specified data from local storage and deseralise it to the specfied type.
16-
/// </summary>
17-
/// <param name="key">A <see cref="string"/> value specifying the name of the local storage slot to use</param>
15+
/// <summary>
16+
/// Retrieve the specified data from local storage and deseralise it to the specfied type.
17+
/// </summary>
18+
/// <param name="key">A <see cref="string"/> value specifying the name of the local storage slot to use</param>
19+
/// <param name="cancellationToken">
20+
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
21+
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
22+
/// </param>
1823
/// <returns>A <see cref="ValueTask"/> representing the completion of the operation.</returns>
19-
ValueTask<T> GetItemAsync<T>(string key);
24+
ValueTask<T> GetItemAsync<T>(string key, CancellationToken? cancellationToken = null);
2025

21-
/// <summary>
22-
/// Retrieve the specified data from local storage as a <see cref="string"/>.
23-
/// </summary>
24-
/// <param name="key">A <see cref="string"/> value specifying the name of the storage slot to use</param>
26+
/// <summary>
27+
/// Retrieve the specified data from local storage as a <see cref="string"/>.
28+
/// </summary>
29+
/// <param name="key">A <see cref="string"/> value specifying the name of the storage slot to use</param>
30+
/// <param name="cancellationToken">
31+
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
32+
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
33+
/// </param>
2534
/// <returns>A <see cref="ValueTask"/> representing the completion of the operation.</returns>
26-
ValueTask<string> GetItemAsStringAsync(string key);
35+
ValueTask<string> GetItemAsStringAsync(string key, CancellationToken? cancellationToken = null);
2736

28-
/// <summary>
29-
/// Return the name of the key at the specified <paramref name="index"/>.
30-
/// </summary>
31-
/// <param name="index"></param>
37+
/// <summary>
38+
/// Return the name of the key at the specified <paramref name="index"/>.
39+
/// </summary>
40+
/// <param name="index"></param>
41+
/// <param name="cancellationToken">
42+
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
43+
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
44+
/// </param>
3245
/// <returns>A <see cref="ValueTask"/> representing the completion of the operation.</returns>
33-
ValueTask<string> KeyAsync(int index);
46+
ValueTask<string> KeyAsync(int index, CancellationToken? cancellationToken = null);
3447

3548
/// <summary>
3649
/// Checks if the <paramref name="key"/> exists in local storage, but does not check its value.
3750
/// </summary>
3851
/// <param name="key">A <see cref="string"/> value specifying the name of the storage slot to use</param>
52+
/// <param name="cancellationToken">
53+
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
54+
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
55+
/// </param>
3956
/// <returns>A <see cref="ValueTask"/> representing the completion of the operation.</returns>
40-
ValueTask<bool> ContainKeyAsync(string key);
57+
ValueTask<bool> ContainKeyAsync(string key, CancellationToken? cancellationToken = null);
4158

42-
/// <summary>
43-
/// The number of items stored in local storage.
44-
/// </summary>
59+
/// <summary>
60+
/// The number of items stored in local storage.
61+
/// </summary>
4562
/// <returns>A <see cref="ValueTask"/> representing the completion of the operation.</returns>
46-
ValueTask<int> LengthAsync();
63+
ValueTask<int> LengthAsync(CancellationToken? cancellationToken = null);
4764

48-
/// <summary>
49-
/// Remove the data with the specified <paramref name="key"/>.
50-
/// </summary>
51-
/// <param name="key">A <see cref="string"/> value specifying the name of the storage slot to use</param>
65+
/// <summary>
66+
/// Remove the data with the specified <paramref name="key"/>.
67+
/// </summary>
68+
/// <param name="key">A <see cref="string"/> value specifying the name of the storage slot to use</param>
69+
/// <param name="cancellationToken">
70+
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
71+
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
72+
/// </param>
5273
/// <returns>A <see cref="ValueTask"/> representing the completion of the operation.</returns>
53-
ValueTask RemoveItemAsync(string key);
74+
ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null);
5475

55-
/// <summary>
56-
/// Sets or updates the <paramref name="data"/> in local storage with the specified <paramref name="key"/>.
57-
/// </summary>
58-
/// <param name="key">A <see cref="string"/> value specifying the name of the storage slot to use</param>
59-
/// <param name="data">The data to be saved</param>
76+
/// <summary>
77+
/// Sets or updates the <paramref name="data"/> in local storage with the specified <paramref name="key"/>.
78+
/// </summary>
79+
/// <param name="key">A <see cref="string"/> value specifying the name of the storage slot to use</param>
80+
/// <param name="data">The data to be saved</param>
81+
/// <param name="cancellationToken">
82+
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
83+
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
84+
/// </param>
6085
/// <returns>A <see cref="ValueTask"/> representing the completion of the operation.</returns>
61-
ValueTask SetItemAsync<T>(string key, T data);
86+
ValueTask SetItemAsync<T>(string key, T data, CancellationToken? cancellationToken = null);
6287

6388
/// <summary>
6489
/// Sets or updates the <paramref name="data"/> in local storage with the specified <paramref name="key"/>. Does not serialize the value before storing.
6590
/// </summary>
6691
/// <param name="key">A <see cref="string"/> value specifying the name of the storage slot to use</param>
6792
/// <param name="data">The string to be saved</param>
93+
/// <param name="cancellationToken">
94+
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
95+
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
96+
/// </param>
6897
/// <returns></returns>
69-
ValueTask SetItemAsStringAsync(string key, string data);
70-
98+
ValueTask SetItemAsStringAsync(string key, string data, CancellationToken? cancellationToken = null);
99+
71100
event EventHandler<ChangingEventArgs> Changing;
72101
event EventHandler<ChangedEventArgs> Changed;
73102
}
Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
using System.Threading.Tasks;
1+
using System.Threading;
2+
using System.Threading.Tasks;
23

34
namespace Blazored.LocalStorage
45
{
56
internal interface IStorageProvider
67
{
78
void Clear();
8-
ValueTask ClearAsync();
9+
ValueTask ClearAsync(CancellationToken? cancellationToken = null);
910
bool ContainKey(string key);
10-
ValueTask<bool> ContainKeyAsync(string key);
11+
ValueTask<bool> ContainKeyAsync(string key, CancellationToken? cancellationToken = null);
1112
string GetItem(string key);
12-
ValueTask<string> GetItemAsync(string key);
13+
ValueTask<string> GetItemAsync(string key, CancellationToken? cancellationToken = null);
1314
string Key(int index);
14-
ValueTask<string> KeyAsync(int index);
15+
ValueTask<string> KeyAsync(int index, CancellationToken? cancellationToken = null);
1516
int Length();
16-
ValueTask<int> LengthAsync();
17+
ValueTask<int> LengthAsync(CancellationToken? cancellationToken = null);
1718
void RemoveItem(string key);
18-
ValueTask RemoveItemAsync(string key);
19+
ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null);
1920
void SetItem(string key, string data);
20-
ValueTask SetItemAsync(string key, string data);
21+
ValueTask SetItemAsync(string key, string data, CancellationToken? cancellationToken = null);
2122
}
2223
}

src/Blazored.LocalStorage/LocalStorageService.cs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Text.Json;
3+
using System.Threading;
34
using System.Threading.Tasks;
45
using Blazored.LocalStorage.Serialization;
56

@@ -16,7 +17,7 @@ public LocalStorageService(IStorageProvider storageProvider, IJsonSerializer ser
1617
_serializer = serializer;
1718
}
1819

19-
public async ValueTask SetItemAsync<T>(string key, T data)
20+
public async ValueTask SetItemAsync<T>(string key, T data, CancellationToken? cancellationToken = null)
2021
{
2122
if (string.IsNullOrWhiteSpace(key))
2223
throw new ArgumentNullException(nameof(key));
@@ -27,12 +28,12 @@ public async ValueTask SetItemAsync<T>(string key, T data)
2728
return;
2829

2930
var serialisedData = _serializer.Serialize(data);
30-
await _storageProvider.SetItemAsync(key, serialisedData).ConfigureAwait(false);
31+
await _storageProvider.SetItemAsync(key, serialisedData, cancellationToken).ConfigureAwait(false);
3132

3233
RaiseOnChanged(key, e.OldValue, data);
3334
}
3435

35-
public async ValueTask SetItemAsStringAsync(string key, string data)
36+
public async ValueTask SetItemAsStringAsync(string key, string data, CancellationToken? cancellationToken = null)
3637
{
3738
if (string.IsNullOrWhiteSpace(key))
3839
throw new ArgumentNullException(nameof(key));
@@ -45,17 +46,17 @@ public async ValueTask SetItemAsStringAsync(string key, string data)
4546
if (e.Cancel)
4647
return;
4748

48-
await _storageProvider.SetItemAsync(key, data).ConfigureAwait(false);
49+
await _storageProvider.SetItemAsync(key, data, cancellationToken).ConfigureAwait(false);
4950

5051
RaiseOnChanged(key, e.OldValue, data);
5152
}
5253

53-
public async ValueTask<T> GetItemAsync<T>(string key)
54+
public async ValueTask<T> GetItemAsync<T>(string key, CancellationToken? cancellationToken = null)
5455
{
5556
if (string.IsNullOrWhiteSpace(key))
5657
throw new ArgumentNullException(nameof(key));
5758

58-
var serialisedData = await _storageProvider.GetItemAsync(key).ConfigureAwait(false);
59+
var serialisedData = await _storageProvider.GetItemAsync(key, cancellationToken).ConfigureAwait(false);
5960

6061
if (string.IsNullOrWhiteSpace(serialisedData))
6162
return default;
@@ -72,33 +73,33 @@ public async ValueTask<T> GetItemAsync<T>(string key)
7273
}
7374
}
7475

75-
public ValueTask<string> GetItemAsStringAsync(string key)
76+
public ValueTask<string> GetItemAsStringAsync(string key, CancellationToken? cancellationToken = null)
7677
{
7778
if (string.IsNullOrWhiteSpace(key))
7879
throw new ArgumentNullException(nameof(key));
7980

80-
return _storageProvider.GetItemAsync(key);
81+
return _storageProvider.GetItemAsync(key, cancellationToken);
8182
}
8283

83-
public ValueTask RemoveItemAsync(string key)
84+
public ValueTask RemoveItemAsync(string key, CancellationToken? cancellationToken = null)
8485
{
8586
if (string.IsNullOrWhiteSpace(key))
8687
throw new ArgumentNullException(nameof(key));
8788

88-
return _storageProvider.RemoveItemAsync(key);
89+
return _storageProvider.RemoveItemAsync(key, cancellationToken);
8990
}
9091

91-
public ValueTask ClearAsync()
92-
=> _storageProvider.ClearAsync();
92+
public ValueTask ClearAsync(CancellationToken? cancellationToken = null)
93+
=> _storageProvider.ClearAsync(cancellationToken);
9394

94-
public ValueTask<int> LengthAsync()
95-
=> _storageProvider.LengthAsync();
95+
public ValueTask<int> LengthAsync(CancellationToken? cancellationToken = null)
96+
=> _storageProvider.LengthAsync(cancellationToken);
9697

97-
public ValueTask<string> KeyAsync(int index)
98-
=> _storageProvider.KeyAsync(index);
98+
public ValueTask<string> KeyAsync(int index, CancellationToken? cancellationToken = null)
99+
=> _storageProvider.KeyAsync(index, cancellationToken);
99100

100-
public ValueTask<bool> ContainKeyAsync(string key)
101-
=> _storageProvider.ContainKeyAsync(key);
101+
public ValueTask<bool> ContainKeyAsync(string key, CancellationToken? cancellationToken = null)
102+
=> _storageProvider.ContainKeyAsync(key, cancellationToken);
102103

103104
public void SetItem<T>(string key, T data)
104105
{
@@ -213,12 +214,12 @@ private ChangingEventArgs RaiseOnChangingSync(string key, object data)
213214
return e;
214215
}
215216

216-
private async Task<T> GetItemInternalAsync<T>(string key)
217+
private async Task<T> GetItemInternalAsync<T>(string key, CancellationToken? cancellationToken = null)
217218
{
218219
if (string.IsNullOrEmpty(key))
219220
throw new ArgumentNullException(nameof(key));
220221

221-
var serialisedData = await _storageProvider.GetItemAsync(key).ConfigureAwait(false);
222+
var serialisedData = await _storageProvider.GetItemAsync(key, cancellationToken).ConfigureAwait(false);
222223

223224
if (string.IsNullOrWhiteSpace(serialisedData))
224225
return default;

0 commit comments

Comments
 (0)