Utilizing Typescript for Promises and leveraging Async-Await for dependent calls

I am currently exploring ways to enhance the performance of data loading by running requests in parallel or considering alternative methods. My background is in Java and I am relatively new to coding in Javascript/Typescript. I recently came across Async-Await and Promises which caught my interest.

Within my code, I have two methods - one that is independent and processes a single request, and another that relies on the output value of other requests (specifically the "number" value).

The sequence in which I call these functions is as follows:

private run(): void {
    this.populatePostTextData(list, 3);
    this.populateCustomerNameData(list, 5);
}

Here are my concerns:

Both methods do not appear to be executing in parallel simultaneously. The flow seems to wait for populatePostTextData() to complete (and update the DOM), then proceed to populateCustomerNameData() (updating the DOM again).

The second method involves two requests and I'm unsure how to structure the await. I attempted to chain them together like so:

await Service.Current.executeRequest(getNumber).then((response: Response) => {
    number = response.items[0]["CustomerNumber"];
    console.log("Customer No retrieved: " + number);
    await Service.Current.executeRequest(getNumber)... 
}).catch((response: Response) => {
    console.log("Error: " + response.errorMessage);
});

However, I encountered an error with

await Service.Current.executeRequest(getNumber)...
indicating it must be within an async function due to nesting. It doesn't seem to recognize it as part of an async method.

First Method

    async populatePostTextData(list: IList, columnNum: number) {
        const columnId = "C" + columnNum;
        for (let i = 0; i < list.getData().getLength(); i++) {
            let referenceOrderNo = list.getData().getItem(i).C1;
            let referenceOrderLine = list.getData().getItem(i).C2;

            const request = new Request("...");
            let postTextData = {};
            await Service.Current.executeRequest(request).then((response: Response) => {
                let postText = response.items[0]["PostText"];
                postTextData[columnId] = postText;
                postTextData["id_" + columnId] = "R" + (i + 1) + columnId;
                $.extend(list.getData().getItem(i), postTextData);
            }).catch((response: Response) => {
                console.log("Error: " + response.errorMessage);
            });
        }
    }
    

Second Method getNumber should execute first as variable number is utilized in getName

    async populateCustomerNameData(list: IList, columnNum: number) {
        const columnId = "C" + columnNum;

        for (let i = 0; i < list.getData().getLength(); i++) {
            let referenceOrderNo = list.getData().getItem(i).C1;
            let referenceOrderLine = list.getData().getItem(i).C2;

            let number = "";
            const getNumber = new Request(".../");
            await Service.Current.executeRequest(getNumber).then((response: Response) => {
                number = response.items[0]["CustomerNumber"];
                console.log("Customer No retrieved: " + number);
            }).catch((response: Response) => {
                console.log("Error: " + response.errorMessage);
            });

            let customerName = {};
            const getName = new Request("...");
            getName.setParam(1,number);
            await Service.Current.executeRequest(getName).then((response: Response) => {
                const name = response.items[0]["CustomerName"];
                customerName[columnId] = name;
                customerName["id_" + columnId] = "R" + (i + 1) + columnId;
                $.extend(list.getData().getItem(i), customerName);
            }).catch((response: Response) => {
                console.log("Error: " + response.errorMessage);
            });
        }
    }

I would greatly appreciate any suggestions or solutions.

Thank you.

Answer №1

It seems like the second request is dependent on the first one being resolved, as you need to pass in the number. In that case, you can try something like this:

const processor = async() => {
    try {
    const result = await initialRequest();
    // At this stage, you can assume that the first request has been successfully completed and you can extract necessary information from the response.
    const number = result.number 
    await subsequentRequest(number);
    } catch(error) {
        console.log(error):
    }
}

Then you can call processor or any other name you prefer whenever you want to start this process. Both request functions should return promises, or they should be async functions which automatically return promises.

You can also utilize the .then keyword or the await keyword to organize the flow of your asynchronous parts within your program. It's possible to use both, but typically one would suffice. If you opt for .then, it could be implemented like this:

const processor = () => {
    initialRequest()
      .then((response) => response.number))
     .then((num) => subsequentRequest(num))
     .catch((error) => console.log(error)):
}

Await is the newer syntax and is generally recommended as it enhances code readability significantly.

Cheers

Answer №2

There doesn't seem to be any obstruction for the second function to run, but it appears that your requests are getting hindered by the await within their respective for loops. You might want to consider using Promise.all or eliminating await for calls you wish to execute concurrently.

This code snippet serves as a demonstration to illustrate the key concepts essential for grasping almost everything about Promises and Async/Await.

let hrstart = process.hrtime();

function time() {
    return `${process.hrtime(hrstart)[0]}s`;
}

function wait(time) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(time);
        }, time * 1000);
    });
}

async function blocking() {
    for (let index = 5; index < 10; index++) {
        let complete = await wait(index);
        console.log('blocking', complete, time());
    }
}

async function single() {
    let complete = await wait(2);
    console.log('single:', complete, time());
}

async function nonBlocking() {
    let jobs = [];
    for (let index = 5; index < 10; index++) {
        jobs.push(wait(index));
    }
    return Promise.all(jobs).then((res) => {
        for (let index = 0; index < res.length; index++) {
            console.log('non-blocking:', res[index], time());
        }
    });
}

blocking();
single();
nonBlocking();

The output produced is as follows:

single: 2 2s
blocking 5 5s
non-blocking: 5 9s
non-blocking: 6 9s
non-blocking: 7 9s
non-blocking: 8 9s
non-blocking: 9 9s
blocking 6 11s
blocking 7 18s
blocking 8 26s
blocking 9 35s

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

Why does the parent URL become the origin for an AJAX request coming from an iframe?

I am facing an issue with a website where I need to load an iframe from a different subdomain. The main website is hosted on portal.domain.com, and the iframe is on iframe.domain.com. To make requests to iframe.domain.com from portal.domain.com, I decided ...

Guide on uploading multiple images in react using Next.js

I am currently facing a challenge with uploading multiple images in React (nextjs) using the <input onChange={onChange} type='file' name='file' multiple/>. I have spent hours searching online for a solution but have not been succe ...

Replace all occurrences of `<span>` with an empty string in a JavaScript string

Looking for a way to remove the span element from an HTML string in JavaScript. var htmlString = '<div>test</div><p>test</p><span class="removedata">X</span><span>test</span><span class="removedata"& ...

"Bringing back the page zoom/scale with the click of a button

I've hit a roadblock as I search for code to tackle my issue. Despite scouring Google and Stackoverflow extensively, I haven't come across anything that addresses my specific problem. Essentially, I have a button on my webpage labeled "Restore s ...

Detecting changes in URL hash using JavaScript - the ultimate guide

What is the most effective method for determining if a URL has changed in JavaScript? Some websites, such as GitHub, utilize AJAX to add page information after a # symbol in order to generate a distinct URL without having to refresh the page. How can one ...

What is the best method to eliminate a "0" entry from a javascript event array?

Hello, I've got an array structured as follows: let test = ["testOne:,O,U,0","testTwo:R,C,0","testTree:1.334","testFour:r,z"]; I'm looking to iterate through the array and remove any occurrences of the cha ...

Each time I invoke the setInterval function, my counter speeds up - using vuejs

In my development process, I am creating a countdown that is triggered by a function. The main objective is to reset the countdown each time a user answers a question in the game and a new question appears. However, I have encountered a challenge where i ...

Error in Angular $injector: Unknown provider

I'm encountering an issue while attempting to implement modals in angular $modalProvider <- $modal <- User.Ctlr Below is my app.js file 'use-strict'; var App = angular.module('App', ['ui.bootstrap']); And here ...

Implementing background color changes based on a database value (sex) using JavaScript

Visualization: [IMG]+[HIDDEN INPUT]-—-[TEXT]-—-[ICON] [IMG]+[HIDDEN INPUT]-—-[TEXT]-—-[ICON] [IMG]+[HIDDEN INPUT]-—-[TEXT]-—-[ICON] (For each individual) I am looking to match the background color of the icon on the right with the IMG on the ...

Retrieve the `access_token` attribute from local storage

I have stored the token in local storage using: localStorage.setItem('token', JSON.stringify(res.data)). Now, I am attempting to retrieve the access_token property. JSON.parse(localStorage.getItem(token['access_token'])) An error is o ...

Ways to incorporate customizable text and images into three.js

Recently, I've been experimenting with adding new images and text as textures to a 3D object using fabric js for my 3D configurator. My codebase is inspired by this GitHub repository, and I'm also utilizing this code from CodePen. One key aspect ...

Double-click to toggle with jQuery

Here is the code for my toggle menu: $(function () { $('#menu li').click(function () { $('#menu li').removeClass("active"); $(this).toggleClass("active"); }); }) It works perfectly, but there is one issue. When ...

What is the best way to retrieve the identifier for a specific role?

Struggling to acquire a channel permissions overwrite by obtaining the ID of a role stored in a variable. Any suggestions on how I can access the ID of this new role? This problem has been consuming my time for several days now. I have experimented with t ...

HTML modal windows are a great way to show

I have a table in an HTML document that is populated with information from JSON. Within one of the cells, I'd like to insert a link that will open a modal window. The current setup functions correctly; however, I would like the modal window to displ ...

Data shared among various RXJS Observables

I am currently in the process of refactoring some code to utilize RXJS and the angular async pipe. The task at hand involves adding and removing items from an array. I'm wondering if there might be a more efficient approach to manipulating a shared ar ...

Implementing text assignment to a textbox field using React Redux

element: MainInput: ); } After successfully fetching student data from the database, I encountered an issue while trying to display the information in a textbox React Field. Even though this.props.firstname displayed the correct value on th ...

Adding days to a HijriDate: A step-by-step guide

I need help with two text boxes. The first box is for selecting the StartDate from an Islamic calendar, which I am currently using jQuery Calendars Datepicker for. The second textbox, ExpireDate, should automatically be set to 60 days after the selected St ...

Angular bar chart tooltip feature malfunctioning

Hey there! I'm currently using an Angular bar chart and it's working smoothly. However, I'm facing an issue with displaying tooltips as the series is not functioning correctly. Below is my code snippet. My goal is to have a tooltip appear wh ...

Are there alternative methods for writing to a JSON file in Angular without relying on the fs module?

Having trouble with the fs module in Angular 7 because of the error message "can't find module fs" when attempting to write to a JSON file. Any suggestions for alternative solutions would be greatly appreciated. ...

I'm looking to integrate Jest in my React project with npm. How can I achieve

I've developed my application with create react app and npm. While reviewing the official documentation for jest at https://jestjs.io/docs/tutorial-react, I noticed that they only provide information on testing CRA apps using yarn. Does this suggest t ...