Divide the list of commitments into separate groups. Carry out all commitments within each group simultaneously, and proceed to the next group

My Web Crawling Process:

I navigate the web by creating promises from a list of website links. These promises act as crawlers and are executed sequentially. For instance, if I have 10 links, I will crawl the first link, wait for it to complete, then move on to the second link, and so on.

What I'm Striving For:

My objective is to organize my promises into groups. Each group will run concurrently, but the groups themselves will run in sequence. As an example, with 10 links, I would generate 10 promises. These promises would then be divided into groups, each containing a maximum of 3 promises. The process would proceed by crawling the first 3 promises (first group), waiting for them to finish, then moving on to the 4th, 5th, 6th promises (second group), and so forth.

My Attempt:

I developed a function to split promises:


        export function splitPromises<T>(promises: Promise<T>[], maxPerItem: number): Promise<T>[][] {
            const splitPromisesList: Promise<T>[][] = [];
            let currentSplit: Promise<T>[] = [];

            for (let i = 0; i < promises.length; i++) {
                currentSplit.push(promises[i]);

                if (currentSplit.length === maxPerItem || i === promises.length - 1) {
                    splitPromisesList.push(currentSplit);
                    currentSplit = [];
                }
            }

            return splitPromisesList;
        }
    

Following this method, I implemented another function that utilizes the splitting and executes promises:


        async function crawler(links: string[], page: Page): Promise<MyData[]> {
            const list: MyData[] = [];

            const crawlPromises = links.map(async (link, index) => {
                try {
                    const newPage = await page.browser().newPage();
                    const detail = await crawlLink(link, newPage);
                    await newPage.close();
                    return detail;
                } catch (e) {
                    console.log(e);
                    return null as MyData;
                }
            });

            const groupedPromises = splitPromises<MyData>(crawlPromises, 3);
            let results: MyData[] = [];

            for (const group of groupedPromises) {
                results = await Promise.all(group);
                const filteredResults: MyData[] = results.filter((detail) => detail !== null) as MyData[];
                list.push(...filteredResults);
            }


          return list;
        }
    

The Challenge:

I seem to be encountering an issue where all promises execute simultaneously instead of following the intended group-based execution pattern.

Answer №1

After the promise is made, the process has already begun. Processing the promises in groups will not cause any delays in the operation. Instead, you should focus on splitting the creation of the promises into batches.

A function that divides an array into smaller chunks can still be helpful, but it should be designed to work with an array of strings rather than just promises:

export function divideArray<T>(array: T[], maxPerItem: number): T[][] {
  const dividedList: T[][] = [];
  // ... the same basic implementation as before, with different variable names
  return dividedList;
}

Next, you need to separate the links and construct an array of promises from that specific chunk. You must wait for each chunk to finish before proceeding to the next one.

async function webCrawler(links: string[], page: Page): Promise<MyData[]> {
  const dataList: MyData[] = [];

  const sections = divideArray(links, 3);

  for (const section of sections) {
    const browsePromises = section.map(async (link, index) => {
      // .. similar to before, except iterating over `section` instead of `links`
    });
    const outcomes = await Promise.all(browsePromises);
    const filteredOutcomes: MyData[] = outcomes.filter((detail) => detail !== null) as MyData[];
    dataList.push(...filteredOutcomes);
  }

  return dataList;
}

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

I'm looking for a way to retrieve an object from a select element using AngularJS. Can

I am working with a select HTML element that looks like this: <select required="" ng-model="studentGroup"> <option value="" selected="">--select group--</option> <option value="1">java 15-1</option> <option value="2">ja ...

Encountering the error message "TypeError: Unable to access properties of null (reading 'get')" while utilizing useSearchParams within a Storybook file

Looking at the Next.js code in my component, I have the following: import { useSearchParams } from 'next/navigation'; const searchParams = useSearchParams(); const currentPage = parseInt(searchParams.get('page') || '', 10) || ...

Guide to sending a post request with parameters in nuxt.js

I am trying to fetch data using the fetch method in Nuxt/Axios to send a post request and retrieve specific category information: async fetch() { const res = await this.$axios.post( `https://example.com/art-admin/public/api/get_single_cat_data_an ...

Creating a dynamic selection in Angular without duplicate values

How can I prevent repetition of values when creating a dynamic select based on an object fetched from a database? Below is the HTML code: <router-outlet></router-outlet> <hr> <div class="row"> <div class="col-xs-12"> & ...

React is still unable to display images when looping, despite the use of the "require"

I am facing an issue with extracting image paths from an array using the map function. The problem is that the image path is being printed as a string instead of rendering as an image. I tried using the require keyword, but I encountered an error stating " ...

Having trouble configuring the proxy port for my Vue.js application

I'm currently developing a web application using vue.js for the front end and node.js for the server. Vue is running on port 8080 and Node.js is running on port 3001. To make API calls, I have set up a proxy in my vue.config.js file, but it doesn&apos ...

Angular - Using HttpClient for handling POST requests

The example provided in the official Angular HttpClient documentation demonstrates how to make a POST request to a backend server. /** POST: add a new hero to the database */ addHero (hero: Hero): Observable<Hero> { return this.http.post<Hero&g ...

Tips for validating user input in AngularJS without using a form tag

Within a popup, I am displaying HTML content that has been copied from another div and shown in the popup. I need to validate this input field to ensure it is required, and display an error message below the input box. <!-- HTML code for changing zip c ...

Extract the Date portion from a DateTime object in ASP.NET MVC

I am currently facing an issue with a property in my Model [Display(Name = "День рождения")] [DataType(DataType.Date)] public System.DateTime Birthday { get; set; } When trying to save the value to the database using AJAX, it is also ...

What is the advantage of parsing values in a switch statement compared to an if condition?

function checkInput() { let value = document.getElementById('test').value; if (value == 1) { console.log("It works with if statement"); } } function checkSwitch() { let value = document.getElementById('test').value; switc ...

How to use jQuery to update the href attribute of a parent link

Can someone help me figure out why I am having trouble changing the 'href' of the parent link to a header logo? Thank you in advance! Here is the HTML code snippet: <a href="https://URL.IWANTO.CHANGE"> <img id="partner_logo" src="/ ...

Send your information without having to navigate away from the current

This is my form <form id="reservationForm" action="sendmail.php" method="post"> ... . . . . <input type="image" src="images/res-button.png" alt="Submit" class="submit" width="251" height="51px"> Here is my javascript $("#reservationForm").su ...

The react-xml-parser package is asking for Babel version "^7.0.0-0", however it was instead loaded with version "6.26.3". I have already attempted all available solutions to resolve this issue

I have attempted numerous solutions from the Github community regarding this issue, but unfortunately none have worked for me. /node_modules/react-xml-parser/dist/bundle.js: Requires Babel "^7.0.0-0", but was loaded with "6.26.3". If you are sure you ha ...

Transferring data from JavaScript to PHP with the help of AJAX

I am encountering issues with my code, as I cannot seem to successfully send coordinates from JavaScript to PHP using AJAX. Although I can retrieve values from JavaScript into a textbox, the values are not being transferred to PHP. Any assistance on resolv ...

Issues arise when using Android BluetoothLeAdvertiser in Nativescript applications

I've been working on creating a Nativescript application that can send Bluetooth low energy advertisements. Since there are no existing Nativescript plugins for this functionality, I decided to develop a Java library (with plans to add a Swift library ...

Determine a deeper hue using Javascript

Is there a way to adjust this calculation to achieve a darker color rather than a brighter one? function increase_brightness(hex, percent){ // strip the leading # if it's there hex = hex.replace(/^\s*#|\s*$/g, ''); // ...

How can I align two inner boxes vertically in the most efficient manner?

.dd{ height:100px; width:100%; border:1px soild red; background:#000; } .dd .d1{ height:20px; width:20px; border:1px solid green; display:inline-block; } .dd .d2{ height:20px; width:20px; border:1px solid green; display:inl ...

React Native package identifies a primary module for handling HTTPS requests

For my latest project, I decided to experiment with incorporating HTTPS. I began by creating a new project using expo init test and then installed the HTTPS library with npm install https. Next, I made edits to App.js by adding the following line at the t ...

Retrieving information from a local JSON file in Vue.js using the jQuery $.getJSON() method

Currently, I am in the process of developing a demo application using Vuejs which involves extracting map data from a local .json file. The extracted data is then used to obtain specific information like latitude and longitude values that are necessary for ...

Creating a CSS circle spinner with a half moon shape is an innovative way to add a unique touch

Image: Circular spinner rotating along the border rim of other solid circle For more details, please visit: https://codepen.io/sadashivjp/pen/oqqzwg I have created a UI codepen here and welcome any modifications or solutions. The code snippet is provided ...