Functional programming and async in action within a while loop implemented in JavaScript

Searching for a way to implement the following code using functional programming techniques.

let membersFound = [];

// Iterate through 50 or more pages until we find 5 members.
while (membersFound.length < 5) {
  let member = findMember(/* Invoke Selenium commands to navigate to next page */);
  if (member !== undefined) {
      membersFound.push(member);
  }
}

console.log(membersFound); // Expected: 5 values, Actual: 0

At present, this code leads to an infinite loop due to the asynchronous nature of JavaScript.

Answer №1

If you modify findMember to return a promise, you can take advantage of ES6 async\await functionality for more streamlined code:

Assuming you currently have a function called findMember(cb), you would transform it into:

function promiseFindMember() {
    return new Promise((resolve, reject) => findMember(member => resolve(member)))
}

With this approach, you can structure your function like so:

async function foo() {
    let members = []
    while(members.length < 5) {
        let member = await promiseFindMember()
        if(member !== undefined) {
            members.push(member)
        }
    }
}

To help grasp the concept and see a comparison between ideas, here's an example:

function dummyCb(cb){
  console.log("Dummy run!")
  setTimeout(cb, 1000)
}

function promiseDummyCb(){
  return new Promise((resolve, reject) => dummyCb(() => resolve()))
}


async function async_hello() {
  cb_count = 0
  while(cb_count < 5) {
    await promiseDummyCb()
    cb_count += 1
  }
}

async function hello() {
  cb_count = 0
  while(cb_count < 5) {
    dummyCb()
    cb_count += 1
  }
}



hello()

Answer №2

To start off, make sure that the function findMember always returns a value by retrying if necessary:

const find = cb => findMember(res => res ? cb(res) : find(cb));

Next, if you want an array of a specific length from a callback function, you can use a similar approach:

const fromAsync = (fn, length, cb, arr = []) => arr.length >= length 
   ? cb(arr)
   :  fn(res => fromAsync(fn, length, cb, arr.concat(res)));

Finally, you can implement it like this:

fromAsync(find, 10, result => {
  console.log(result);
});

Note: There may be simpler ways to achieve the same result, but if you prefer a functional approach, this is one way to go about it...

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

Simple yet perplexing JavaScript within an Angular directive

In the tutorial, the author explains that each element in the stars array contains an object with a 'filled' value, which is determined as true or false based on the scope.ratingValue received from the DOM. directive('fundooRating', fu ...

How can you ensure that it selects a random number to retrieve items from an array?

I am experiencing an issue with some code I wrote. Instead of displaying a random object from the array as intended, it is showing the random number used to try and display an object. <html> <body> <h1>HTML random objects< ...

What is the best method for transferring formatted text from the clipboard to an HTML textarea?

When you copy and paste from a web browser to a text processor, the HTML markup gets converted to rich text. The text processor then tries to convert this markup into its own format, proving that the Clipboard can hold markup. However, when you copy and p ...

Utilize React Hook Form to easily reset the value of an MUI Select component

I created a dropdown menu where users can select from "Item 1", "Item 2", and "Item 3". Additionally, there is a "Reset" button that allows users to clear their selection and make a new one. Below is the code I used: import React from ...

What is the best way to shrink or enlarge individual sections of the accordion?

Exploring AngularJs Accordions I'm struggling to understand how to control accordions in AngularJS. I have a step-by-step module set up as an accordion and I want to collapse one part while expanding another based on completion. Here is the accordion ...

Typescript Routing Issue - This call does not match any overloads

Need assistance with redirecting to a sign-up page upon button click. Currently encountering a 'no overload matches this call' error in TypeScript. Have tried researching the issue online, but it's quite broad, and being new to Typescript ma ...

How can I identify the nearest ancestor based on a specific class in Angular 8?

In order to achieve a specific goal, let's imagine this scenario: Object A Object B Object C Object D Object D represents my angular component. It is important for me to adjust its height based on the heights of Object A and Object B. Regardle ...

Error encountered: Jquery counter plugin Uncaught TypeError

I am attempting to incorporate the JQuery Counter Plugin into my project, but I keep encountering an error: dashboard:694 Uncaught TypeError: $(...).counterUp is not a function <!DOCTYPE html> <html lang="en"> <head> <script src ...

Utilizing Promise.all to update subdocuments with Mongoose

Encountered an error while checking the value in promiseArr, seeking assistance or suggestions for a better approach. Thanks! **Error** <rejected> { MongooseError: Callback must be a function, got [object Object] at new MongooseError (D:\P ...

What is the best way to iterate through multiple iframes?

I need help figuring out how to load one iframe while having the next one in line to be displayed. Is there a way to create a script that cycles through multiple iframes after a certain amount of time? ...

An issue arose in Leaflet where drawing on the map became impossible after making an update to a marker's position

I have been working with Leaflet, Leaflet-draw, and Cordova Geolocation. Initially, when the map is loaded in globe view, drawing works perfectly. However, when the locate function is called to update the map center and marker position, drawing becomes imp ...

Issue with JQuery Event Listener on Canvas Subelement not functioning

I encountered an issue while trying to implement a custom crop rectangle on a canvas using JavaScript. I created a function that, when called, should add a child node to the existing canvas and use JQuery listeners to draw the rectangle. However, although ...

Issue with AddToAny plugin not functioning properly on FireFox

I’m having issues with AddToAny for social media sharing on my website. It seems like FireFox is blocking it because of tracking prevention measures. Error Message in Console: The resource at “https://static.addtoany.com/menu/page.js” was blocked d ...

What is the best way to pinpoint a specific Highcharts path element?

I am currently working on drawing paths over a graph, and I am looking to dynamically change their color upon hovering over another element on the page - specifically, a list of data points displayed in a div located on the right side of my webpage. Below ...

Maintain original image file name when downloading

I have successfully created a download link containing a base 64 encoded image. The only issue is that I need to retain the original file name, which is dynamic and cannot be hardcoded. downloadImage: function(){ var image_url = document.getEleme ...

Having difficulty processing information retrieved from an ajax request in jQuery

Upon making a request to the server and converting the retrieved data into a table format, I utilize jQuery's .html() function to display it on the webpage. However, despite the data being visible on the page, I encounter issues when attempting to man ...

Authenticating with passportjs using a Google Apps email address for verification

I am currently experimenting with using Passport.js along with a Google Apps email ID. I have successfully been able to authenticate using a gmail.com email ID, however, I am facing challenges when attempting to authenticate if the email ID is associated w ...

Guide to printing elements from an ArrayList in Java

I need help with randomly selecting and printing an item from an ArrayList that I created from an Array. Can someone provide guidance on how to achieve this? The code snippet below shows what I have done so far. public class Song { final String[] s ...

The 'Cross domain jQuery Ajax request using JSONP' triggered an error: SyntaxError - Unexpected token : appeared on the screen

I've been struggling to extract information from the steam api, encountering persistent difficulties due to the error mentioned above. Below is the snippet of code I have been utilizing: var steamurl = "https://api.steampowered.com/IDOTA2Match_570/Ge ...

Unable to see the column filter in the data table

My datatable setup includes the column filter js on the page, everything is displaying and working smoothly without any errors in the console. However, after the smoothness loads, the inputs at the bottom are not visible. <body> <div id="stab ...