Promise and Promise<T> are JSObject wrappers for the JavaScript Promise class. They allow creating JavaScript Promises from .NET code - wrapping async methods, Tasks, or TaskCompletionSource instances.
Namespace: SpawnDev.BlazorJS.JSObjects
JavaScript Promises are the async primitive - the equivalent of .NET's Task. SpawnDev.BlazorJS lets you:
- Create Promises from .NET to pass to JavaScript APIs that expect them
- Await Promises returned from JavaScript
- Bridge Task and Promise for seamless async interop
var promise = new Promise(async () =>
{
await Task.Delay(5000);
// Promise resolves when the lambda completes
});
// Pass to a JS API that expects a Promisevar promise = new Promise<string>(async () =>
{
await Task.Delay(5000);
return "Hello world!";
});
// Promise resolves with the return valuevar promise = new Promise(() =>
{
// Synchronous work - resolves immediately
});var taskSource = new TaskCompletionSource<string>();
var promise = new Promise<string>(taskSource.Task);
// Pass promise to JavaScript API immediately
JS.Set("myPromise", promise);
// Resolve later
taskSource.TrySetResult("Hello world!");Task<byte[]> downloadTask = httpClient.GetByteArrayAsync(url);
var promise = new Promise<byte[]>(downloadTask);Await the resolution of a Promise from JavaScript:
// Get a Promise from JavaScript
using var promise = JS.Call<Promise<string>>("fetchData", "/api/items");
// Await the result
string result = await promise.ThenAsync();The more common pattern is to use CallAsync<T>, which handles the Promise awaiting internally:
// This is equivalent to getting the Promise and calling ThenAsync
string result = await JS.CallAsync<string>("fetchData", "/api/items");Another alternative:
string result = await JS.Call<Task<string>>("fetchData", "/api/items");Some JavaScript APIs accept Promises as parameters. The Web Locks API is a good example - the lock is held until the Promise you return resolves.
using var navigator = JS.Get<Navigator>("navigator");
using var locks = navigator.Locks;
Console.WriteLine("Requesting lock...");
// Request a lock - the callback must return a Promise
// The lock is held until the Promise resolves
using var waitLock = locks.Request("my_lock",
Callback.CreateOne((Lock lockObj) => new Promise(async () =>
{
Console.WriteLine("Lock acquired");
await Task.Delay(5000);
Console.WriteLine("Lock released");
}))
);
// Request the same lock - will wait until the first one releases
using var waitLock2 = locks.Request("my_lock",
Callback.CreateOne((Lock lockObj) => new Promise(async () =>
{
Console.WriteLine("Second lock acquired");
await Task.Delay(5000);
Console.WriteLine("Second lock released");
}))
);Output:
Requesting lock...
Lock acquired
Lock released
Second lock acquired
Second lock released
When a Callback wraps an async method (returning Task or Task<T>), the return value is automatically converted to a JavaScript Promise:
// This callback returns a Promise to JavaScript
JS.Set("myAsyncFn", Callback.CreateOne<string, Task<string>>(async (input) =>
{
await Task.Delay(1000);
return $"Processed: {input}";
}));// JavaScript:
var result = await myAsyncFn("test");
// result == "Processed: test"| Member | Description |
|---|---|
ThenAsync() |
Awaits the Promise resolution and returns the result |
Constructor Promise(Action) |
Create from sync void lambda |
Constructor Promise(Func<Task>) |
Create from async void lambda |
Constructor Promise<T>(Func<Task<T>>) |
Create from async lambda with return value |
Constructor Promise<T>(Task<T>) |
Create from an existing Task |
- BlazorJSRuntime - CallAsync for awaiting Promise-returning JS methods
- Callbacks - Async callbacks auto-convert to Promises