Exploring the concept of making nested API requests within a route using Node.js and

Being a newbie in the world of coding, I'm excited to make my first post here. My current learning project involves developing a website that utilizes an external CRM for storing client data received from web forms.

The storage functionality is up and running smoothly, but I'm facing challenges when it comes to fetching the data and passing it to a rendered page. I require a route to carry out three operations sequentially, each working fine individually but struggling to nest them effectively.

  1. Obtaining details of a deal from the CRM
var options = { method: 'GET',
                    url: 'https://crm.com/dev/api/opportunity/' + req.params.id,
                    headers: 
                        { 'cache-control': 'no-cache',
                         'content-type': 'application/json',
                          accept: 'application/json',
                          authorization: 'Basic xxx' },
                          json: true };
            request(options, function (error, response, body) {
                if (error) throw new Error(error);
                    return body.contact_ids;
            });

This request will provide an array of client numbers associated with the deal.

  1. Iterating through the client numbers to retrieve data from each client and store it in an array. I have initialized an empty array named data outside the function scope to capture the results.

         resultFromAboveRequest.forEach(function(id) {               
            var options = { method: 'GET',
                 url: 'https://crm.com/dev/api/contacts/' + Number(id),
                 headers: 
                  { 'cache-control': 'no-cache',
                     'content-type': 'application/json',
                     accept: 'application/json',
                     authorization: 'Basicxxx' },
                    json: true };
    
             request(options, function (error, response, body) {
    
                if (error) throw new Error(error);
                data.push(body);
            });
        });
    
  2. Displaying the resulting data array on a webpage

    res.render("./applicants/resume", {data: data});

I believe utilizing promises would be ideal for this task, but I am having difficulty grasping the syntax. Any assistance would be greatly appreciated. My apologies if the format of this question appears amateurish or inappropriate in any way.

Answer №1

If you want to efficiently manage a series of asynchronous operations with proper sequencing and error handling, I recommend utilizing the request-promise library. This library serves as a promise-based interface to the standard request library, allowing for smoother operation flow.

const rp = require('request-promise');

const options = {
    method: 'GET',
    url: 'https://crm.com/dev/api/opportunity/' + req.params.id,
    headers: {
        'cache-control': 'no-cache',
        'content-type': 'application/json',
        accept: 'application/json',
        authorization: 'Basic xxx'
    },
    json: true
};
rp(options).then(body => {
    return Promise.all(body.contact_ids.map(id => {
        const options = {
            method: 'GET',
            url: 'https://crm.com/dev/api/contacts/' + Number(id),
            headers: {
                'cache-control': 'no-cache',
                'content-type': 'application/json',
                accept: 'application/json',
                authorization: 'Basicxxx'
            },
            json: true
        };
        return rp(options);
    }));
}).then(data => {
    res.render("./applicants/resume", {data: data})
}).catch(err => {
    console.log(err);
    res.status(500).send("internal server error");
});

To break down the process:

  1. Integrate the request-promise library which returns promises instead of completion callbacks, ensuring better management of async tasks.
  2. Initiate the first request using .then() handler to extract the outcome.
  3. Utilize .map() to process the received result effectively.
  4. In each iteration of .map(), return another promise by calling request-promise accordingly to generate an array of promises.
  5. Employ Promise.all() on this array of promises for synchronization purposes.
  6. Chaining the returned promise from Promise.all() ensures sequential execution post previous actions' completion.
  7. Implement another .then() to access ordered data from .map() for rendering via res.render().
  8. For error mitigation, incorporate a .catch() block to capture any issues within the promise chain, redirecting them to trigger appropriate error responses.

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

The length function appears to be signaling an unanticipated error

Recently, I encountered an issue with the code execution. Although the code appears to be functioning correctly, it is throwing an uncaught error. Is there a reason for concern regarding this situation? var xmlhttp = new XMLHttpRequest(); xmlhttp.onread ...

Leveraging an Array of Objects in JavaScript

Need help with my JavaScript code! I want to adjust the date in a Date object by adding specific days and then save it. Here is what I have so far: let orderIdDateCorrectionDict = [ { "orderId": "2020053100", "dayCorrection": -146 }, { "orderId" ...

Access Java-generated cookies in JavaScript

I'm currently working on setting cookies using Java as demonstrated here. My goal is to utilize this cookie in JavaScript (it's necessary to do it this way due to certain limitations). However, I'm unable to detect any set cookies (using th ...

Floating navigation bar that appears and disappears as you scroll

My webpage has a dynamic navbar that consists of two parts: navbarTop and navbarBottom. The navbarTop should appear when the user has scrolled down more than 110 pixels, while the navbarBottom should show up when the user scrolls up. The issue I am facing ...

Conceal the object, while revealing a void in its place

Is there a way to hide an image but keep the containing div blank with the same dimensions? I want it to appear as if no content was there, maintaining the original width and height. For example: http://jsfiddle.net/rJuWL/1/ After hiding, "Second!" appea ...

Implementing adaptive window.scrollY listener in React to account for different screen sizes

I am currently using a useEffect hook to create a fade-in effect for text based on scroll position. While this works perfectly on my 27-inch MAC screen, I am facing challenges when viewing it on a smaller screen. I am unsure how to adjust the useEffect to ...

What is the best way to add a button to every row in Titanium Studio?

Is there a way to add a different button inside each row (createTableViewRow)? I have created five buttons using Titanium.UI.createButton, but I'm struggling to figure out how to place all five buttons in every row. Can someone provide some guidance o ...

Offering various language options on a website determined by the URL

I've been contemplating how to add multi-language support to my personal website, which I developed using ExpressJS and NodeJS with EJS as the template engine. Currently, the website is only available in English, but I want to add a German version as ...

Every time Fetch() is called in Node.js, a fresh Express session is established

Here is a snippet of code from a webshop server that includes two APIs: ./login for logging in and ./products to display products. The products will only be displayed after a successful login. The server uses TypeScript with Node.js and Express, along wit ...

What Sets Apart Webpack from Express?

Just starting out with Webpack. With Webpack, I have the ability to create a server. However, I can also use express to achieve the same goal. What sets webpack-dev-server apart from express servers, and when is it best to use each? ...

Chrome not triggering the fullscreenchange event

I've been attempting to track when the browser goes into fullscreen mode. Everywhere I look, this blog is mentioned as the go-to resource on the fullscreen API. According to this SO answer, it should work. Fullscreen API: Which events are fired? B ...

Get the latest html content and save it as a .html file using javascript or jQuery

Looking for a way to save an HTML page as a .html file? Having some trouble with jQuery modifications not being included in the exported file? Check out the code snippet below and let me know if you can spot what's going wrong! I'm still getting ...

Using WHERE clause effectively in an UPDATE statement in Node.js

Today, I have encountered an issue with my code that I would like to address. The problem lies in the PUT method where it currently updates all rows in the table instead of just the matched rows. How can I ensure that only the matched rows are updated? ...

Is there a more efficient method to gather properties from an object into separate arrays without the need for using `map` twice?

Currently, my code block looks like this: res.json({ dates: rows.map(function (item) { return item.Date }), counts: rows.map(function (item) { return item.NewMembers }) }); While functional, I can't help but feel it is inefficient as the row ...

Customize bullet list icons to adjust in size based on content using css

In my CMS project, the CMS team has a special requirement regarding unordered and ordered lists. They want the size of the bullet list icon to adjust according to the text content within the list. The image below shows the default design of a list item: ...

Issue on Heroku with Discord.js displaying a "Service Unavailable" message

Encountered a strange error while trying to launch my discord bot on heroku. Previously, I implemented a command handler for the bot to organize commands in separate files but faced multiple code errors. With the help of a member from this community, all e ...

Assign a temporary value to the Select component in Material UI version 1.0.0-beta.24

I am currently working on a test project using Material UI v1.0.0-beta.24, and I have noticed that the "Dropdown" menus behave differently compared to the previous version. What I am trying to achieve is setting up a placeholder in the Select component. P ...

I am encountering difficulties with hosting a project that was created using Next.js

I am currently working on a Next.js project and I encountered some version compatibility issues when integrating MUI. While my project runs smoothly in localhost, it fails to work when deployed in hosting. I attempted to resolve this by using the --legacy ...

Is it possible to chain multiple method calls on slim's response object for increased efficiency?

When attempting to chain multiple method calls on Slim's $response object, I encounter an error (status 500) and no action is taken. This could be due to my limited PHP knowledge, as I am relatively inexperienced with PHP and this is my first time wor ...

"Use jQuery to toggle the slide effect for the first element of a

Below is the HTML code snippet: <div class="row header collapse"> Content 1 <i class="fas fa-chevron-circle-up" ></i> </div> <div class="instructions-container"> <div></di ...