//-----------------------------------------------------------------------
//
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information.
//
//-----------------------------------------------------------------------
namespace AliasVault.Admin.Services;
using Microsoft.JSInterop;
///
/// Service for invoking JavaScript functions from C#.
///
public class JsInvokeService(IJSRuntime js)
{
///
/// Invoke a JavaScript function with retry and exponential backoff.
///
/// The JS function name to call.
/// Initial delay before calling the function.
/// Maximum attempts before giving up.
/// Arguments to pass on to the javascript function.
/// Async Task.
public async Task RetryInvokeAsync(string functionName, TimeSpan initialDelay, int maxAttempts, params object[] args)
{
TimeSpan delay = initialDelay;
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
try
{
bool isDefined = await js.InvokeAsync("isFunctionDefined", functionName);
if (isDefined)
{
await js.InvokeVoidAsync(functionName, args);
return; // Successfully called the JS function, exit the method
}
}
catch
{
// Optionally log the exception
}
// Wait for the delay before the next attempt
await Task.Delay(delay);
// Exponential backoff: double the delay for the next attempt
delay = TimeSpan.FromTicks(delay.Ticks * 2);
}
// Optionally log that the JS function could not be called after maxAttempts
}
///
/// Invoke a JavaScript function with retry and exponential backoff that returns a value.
///
/// The type of value to return from the JavaScript function.
/// The JS function name to call.
/// Initial delay before calling the function.
/// Maximum attempts before giving up.
/// Arguments to pass on to the javascript function.
/// The value returned from the JavaScript function.
/// Thrown when the JS function could not be called after all attempts.
public async Task RetryInvokeWithResultAsync(string functionName, TimeSpan initialDelay, int maxAttempts, params object[] args)
{
TimeSpan delay = initialDelay;
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
try
{
bool isDefined = await js.InvokeAsync("isFunctionDefined", functionName);
if (isDefined)
{
return await js.InvokeAsync(functionName, args);
}
}
catch
{
// Optionally log the exception
}
// Wait for the delay before the next attempt
await Task.Delay(delay);
// Exponential backoff: double the delay for the next attempt
delay = TimeSpan.FromTicks(delay.Ticks * 2);
}
// All attempts failed, throw an exception
throw new InvalidOperationException($"Failed to invoke JavaScript function '{functionName}' after {maxAttempts} attempts.");
}
}