Tips on how to efficiently yield a resolving Promise Like object from a for loop

In my custom function, I have a promise-like object that decrypts a given message using the web crypto API. The issue is that in my decryption function, I need to test several different values as input and run this promise-like object multiple times in a for loop. Ultimately, I want the function to return whichever of these promises successfully resolves.

public decryptMessage(latitude: [string, number], longitude: [string, number], ciphertext: string) {
    // Retrieve salt 
    const salt = localStorage.getItem("salt");
    const retrievedSaltArray = JSON.parse(salt);
    const saltBytes = new Uint8Array(retrievedSaltArray);

    // Retrieve IV
    const iv = localStorage.getItem("iv");
    const retrievedIvArray = JSON.parse(iv);
    const ivBytes = new Uint8Array(retrievedIvArray);

    // Get tolerance distance
    let toleranceDistance = parseInt(JSON.parse(localStorage.getItem("toleranceDistance")));

    // Get original keyHash
    let originalHash = localStorage.getItem("keyhash");

    // Create location inputs (locations with adjacent quadrants)
   let location = new Location(latitude, longitude);
   let locationInputs = location.prepareReceiverLocationInputs();

   let encryptionTool = new EncryptionHelper(saltBytes, ivBytes);

    for (let i = 0; i <= locationInputs.length - 1; i++) {
      let plaintText = encryptionTool.decrypt(locationInputs[i], ciphertext, originalHash);
       plaintText.then(function(plaintTextResult) {
            return plaintTextResult;
        });
    }

}

Essentially, I am trying to run the encryptionTool.decrypt() method in a for loop so that the return value of the decryptMessage method is whichever promise resolves successfully. However, since this method uses the webcrypto API, it does not have reject or catch methods as it is a promise-like method.

Answer №1

When dealing with promises, it's important to remember that they represent values that will be available in the future. This means you can't test them synchronously to see which one succeeds. Instead, you have to utilize functions for manipulating and combining promises effectively. If encryptionTool.decrypt returns a value wrapped in a promise-like object, you can handle it as follows:

To start, use Promise.resolve to convert the promise-like object to a genuine promise. Then, employ Promise.all to process an array of promises simultaneously and retrieve the desired result through a then callback. Keep in mind that if any promise within the array rejects, all results are lost. To safeguard against this, use catch before utilizing Promise.all to map rejections to a default value like null. The code snippet below exemplifies this approach:

// Assuming encryptionTool.decrypt returns a PromiseLike<string>,
// promises will be a Promise<string | null>[].
let promises = [];
for (let i = 0; i <= locationInputs.length - 1; i++) {
    promises.push(
        Promise.resolve(encryptionTool.decrypt(locationInputs[i], ciphertext, originalHash))
        .catch((error) => null));
}
return Promise.all(promises).then((results) => {
    // Process results to find and return the non-null value.
});

The final then call generates a promise containing the ultimate result, which is then returned synchronously to the caller of decryptMessage.

An alternative option involves making decryptMessage an async function for a more straightforward programming style. By changing public decryptMessage to public async decryptMessage, you can structure your code differently as shown below:

for (let i = 0; i <= locationInputs.length - 1; i++) {
    try {
        return await encryptionTool.decrypt(locationInputs[i], ciphertext, originalHash);
    } catch (e) {
        // Handle exception and proceed accordingly.
    }
}
// Decide on a fallback plan if all decryptions fail.

Note that this sequential decryption method may lead to longer processing times based on the implementation of the web crypto API.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Combining rxjs events with Nestjs Saga CQRS

I am currently utilizing cqrs with nestjs Within my setup, I have a saga that essentially consists of rxjs implementations @Saga() updateEvent = (events$: Observable<any>): Observable<ICommand> => { return events$.pipe( ofType(Upd ...

Creating a Vue select list by populating it with an array of options and automatically selecting one based on an asynchronous response

I've been experimenting with Vue to create a select list using a predefined array of options. However, when a specific async response or event contains an assignee, I set that as the 'currentAssignee' which is then preselected in the list. ...

What causes the Cassandra client driver to provide more detailed information compared to cqlsh?

I'm currently utilizing the datastax nodejs-driver to retrieve information about a keyspace from cassandra. const results = await client.execute( ` DESC KEYSPACE ${keyspace} ` ); The method client.execute provides a comprehensive object containin ...

Avoiding unnecessary re-renders of a parent component caused by a child component

I'm facing rendering problems and would greatly appreciate any assistance. I attempted to use useMemo and useCallback, but it resulted in the checkbox breaking. Within a component, I am displaying information from an object. Let's consider the fo ...

Do I require a Javascript framework, or can I achieve the desired functionality with the

During my time building Microsoft Excel apps using VBA, I worked with events like _Change and _Click. Transitioning to JavaScript and frameworks was a bit overwhelming due to the asynchronous nature of it all. Moving on to Python and Flask has been a ref ...

Show a single jQuery Validation error

I am struggling with displaying an error message at the top if validation fails, without using the errorPlacement option. Instead, I want to showcase the message in a Bootstrap alert box. Below is the HTML code snippet: <form method="POST" action="/ro ...

You have encountered an error: [ERR_HTTP_HEADERS_SENT]. This means that you cannot set headers after they have already been sent to the client, even if a return

I've encountered a 'Cannot set headers after they are sent to the client' error with the /api/users/profile route and have been attempting to resolve it. I stumbled upon some solutions on stackoverflow suggesting to add a return statement - ...

Removing Form Fields Utilizing Javascript

Is it possible to create a unique function in Javascript that automatically removes a form field if it remains unfilled? <form id="myform"> <label for="q1" id="q1label">question 1</label> <input type="text" id="q1" name="q1"/> < ...

Tips for minimizing the use of if-else statements in JavaScript (specifically in Node.js)

Depending on a specific parameter, the function needs to choose from over 100 JSON files and send a query to another system. There will be numerous queries, possibly in the hundreds. Using if else and switch statements would not be practical for managing ...

Is the utilization of the React context API in NextJS 13 responsible for triggering a complete app re-render on the client side

When working with NextJS 13, I've learned that providers like those utilized in the React context API can only be displayed in client components. It's also been made clear to me that components within a client component are considered part of the ...

When you're downloading a file in Safari, the filename ends up being displayed as 'unidentified'

I am encountering an issue with the code I implemented that downloads a file in Safari, but the filename appears as 'untitled'. Interestingly, it works fine in other browsers. var saveData = (function () { var base64 = "data:application/mswo ...

Executing a JavaScript Function in the Background using Cordova

Despite the numerous questions and plugins available on this topic, finding a solution has proven to be elusive for me. The most highly recommended plugin for this issue can be found here. My goal is to run MyService in the background, subscribe to the ON ...

Navigating through different components in Angular without using templates

Searching for a straightforward solution using Angular to manage routes. I have a webpage generated by the server featuring a basic Google map and some logic spread across three separate controllers. Now, I aim to integrate routing into this setup. Nothi ...

Step by step guide to creating individual counter sections

I have set up a counter section where the numbers go from 0 to a specific value. However, currently all three counters start counting simultaneously. Is there a way for the first counter to count up first, then once it's done, move on to the second c ...

change the width of a div element to match that of its nearest sibling element

Can the width of a div be automatically set to match its closest sibling when the width is set to width: auto;? In my coding example on jsFiddle, you can observe three colored divs - red, green, and blue. I am aiming for the blue div to adjust its size ba ...

Separate an array in TypeScript based on the sign of each number, and then replace the empty spaces with null objects

Hey, I'm facing a little issue, I have an Array of objects and my goal is to split them based on the sign of numbers. The objects should then be dynamically stored in different Arrays while retaining their index and getting padded with zeros at the b ...

Error in Angular service: receiving undefined value

logdetail.service.ts import { Injectable } from '@angular/core'; import { LogDetail } from './logdetail.model'; import { HttpClient } from "@angular/common/http"; @Injectable({ providedIn: 'root' }) export class LogdetailSe ...

How to refer to a dynamic instance of @ContentChild in Angular 2

I am currently working with Angular 2.0.1. One of my components can accept any other component using <ng-content>, and this functionality is working well. However, I face a challenge when trying to reference the injected component. If I knew that ...

Customize your popover content with Bootstrap settings

I've been on a quest to dynamically update the content of a Bootstrap popover using JavaScript, but unfortunately, the methods I've tried so far haven't worked out as expected : <!--object with the popover--> <input id="popoverlist ...

Using JQuery, it is possible to search for elements by one specific class while excluding others

Looking for a way to target elements with a specific class, but only if they don't have another class attached to them. Here is an example: <li class="target-class exclude-class"></li> <li class="target-class exclude-class"></li& ...