//----------------------------------------------------------------------- // // 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."); } }