Struggling with effectively executing chained and inner promises

It seems like my promises are not completing as expected due to incorrect handling. When using Promise.all(), the final result displayed with console.log(payload) is {}. Ideally, it should show something similar to this:

{
  project1: {
    description: '...',
    stats: {python: 50, css: 50}
  },
  project2: {
    description: '...',
    stats: {python: 25, css: 75}
  },
  project3: {
    description: '...',
    stats: {python: 10, css: 90}
  }
}

Here's the code snippet in question:

app.get("/github", (req, res) => {
    const authorizationHeader = {headers: {Authorization: 'Basic ' + keys.github.accessToken}};
    const user = 'liondancer';
    const githubEndpoint = 'api.github.com/repos/';
    var payload = {};
    let promises = req.query.projects.map(project => {
        let datum = {};
        const githubAPIUrl = path.join(githubEndpoint, user, project);
        return fetch('https://' + githubAPIUrl + '/languages', authorizationHeader).then(res => {
            // Get Languages of a project
            if (!isStatus2XX(res)) {
                throw 'Status code not 2XX:' + res.status;
            }
            return res.json();
        }).then(res => {
            let languagePercentages = {};
            let total = 0;
            // get total
            Object.keys(res).forEach(key => {
                total += Number.parseInt(res[key]);
            });
            // compute percentages
            Object.keys(res).forEach(key => {
                languagePercentages[key] = (Number.parseInt(res[key]) / total * 100).toFixed(1);
            });
            datum.stats = languagePercentages;
            // Get description of a project
            fetch('https://' + githubAPIUrl).then(res => {
                if (!isStatus2XX(res)) {
                    throw 'Status code not 2XX: ' + res.status;
                }
                return res.json();
            }).then(res => {
                datum.description = res.description;
                payload[project] = datum;
            });
        }).catch(err => {
            console.log('Github API error: ' + err);
        });
    });

    Promise.all(promises).then(() => {
        console.log(payload);
        res.send(payload);
    }).catch(err => {
        console.log('nothing ever works...: ' + err);
    });
});

Initially, changing .map to .forEach() seemed to make the code work correctly and payload had the anticipated values. However, when trying to send the collected results, I encountered difficulties executing the promises in the correct order, or at all.

Answer №1

modify this line

fetch('https://' + githubAPIUrl).then(res => {

to this

return fetch('https://' + githubAPIUrl).then(res => {

this will ensure that promise.all resolves only after all nested promises have been resolved and the payload is filled up.

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

What is the best way to launch a Popup window that spans from the top to the bottom of the screen?

I'm attempting to create a popup window that stretches from the top of the screen to the "applications" bar in Windows. Here's the code I'm using: function windowOpener(windowHeight, windowWidth, windowName, windowUri) { var windowHeight = ...

How can we efficiently loop through all the icons in React Material-UI?

I am looking to iterate over all the icons from @material-ui/icons in a React application. If I want to import a single icon, I can do so like this import IconNameIcon from '@material-ui/icons/IconName' and then use it in my component like th ...

Creating a new attribute within a JavaScript object by utilizing the properties of its sibling elements

Imagine a scenario where you have a complex array of objects structured like this: [ { "title": "Fundamentals", "order": 1, "lessonRef": "fundamentals", "children": [ { "title": "History", "order": 1, "lesso ...

How can permissions for video and audio be configured in Next.js?

When the button is clicked, I want to set permissions. This is how I'd like the scenario to play out: first, the method works initially and allows permission when the button is pressed. Here is my code: <button onClick={requestPermission} classN ...

developing a system in Node.js for organizing regular occurrences in a MySQL database table

My database contains a table named tasks. Within this table, users have the ability to create either a standard task or a recurring task. Recurring tasks automatically generate new entries in the MySQL tasks table and notify users via email of the newly cr ...

Can you elaborate on the contrast between React Server Components (RSC) and Server Side Rendering (SSR)?

I'm curious about the differences between RSC in React 18 and SSR in NextJS. Can anyone explain? ...

Encountering connection reset issue while attempting to access Docker Express API Endpoint on a Windows 10 system

I recently installed Docker For Windows on my Windows 10 machine. As a beginner to Docker, I decided to create an Express/Mongo API service by following this tutorial. After setting up the image with this command: docker-compose -f docker/docker-compos ...

Having trouble getting Javascript Jquery to function properly?

There is a button that, when clicked, changes the HTML in the body tag to include a new button. However, when this new button is clicked, it should trigger an alert message but it is not working as expected. I suspect that the issue lies with the document ...

Docz: Utilizing Typescript definitions for props rendering beyond just interfaces

We are currently using Docz to document our type definitions. While it works well for interfaces, we've run into an issue where rendering anything other than interfaces as props in Docz components doesn't seem to display properly. I'm seeki ...

The CSS property overflow-x:hidden; is not functioning properly on mobile devices despite trying multiple solutions recommended online

Seeking help on a persistent issue, but previous solutions haven't worked for me. Looking to implement a hamburger menu that transitions in from offscreen. The design appears correctly on desktop and simulating mobile, but actual mobile view require ...

Implementing dynamic props in Vue2 component by passing arbitrary named variables

Having recently delved into Vue, I am facing a challenge that has left me scratching my head after consulting the documentation: I am struggling to pass an arbitrarily named variable as a prop to a component instance. As per my understanding, props serve ...

Adding and storing extra form elements using JavaScript: Guidance on integrating Stripe functionality

My goal is to save data from additional inputs in the form, besides just the credit card details. Here is a preview of the form: form image While the payment process and booking storage in the database are functioning correctly, I'm facing a challe ...

My JavaScript/jQuery code isn't functioning properly - is there a restriction on the number of api calls that can be made on

Below is the code I have implemented from jquery ui tabs: <script> $(function(){ // Tabs $('#tabs1').tabs(); $('#tabs2').tabs(); $('#tabs3').tabs(); //hover states on the sta ...

Identify the nested Object within the Json data

I am looking to add and name a nested object within my Json data structure. The current structure of my Json is as follows: { "MH": [ { "MHF46": "Ledig", "MHF60": "60", }, ...

What is the method for creating a MongoDB collection index that enforces uniqueness in a case-insensitive manner?

When designing a user schema, I require usernames to be case insensitive, ensuring no two usernames are similar even when taking into account capital letters. To achieve this, I initially added collation with a locale of 'en' and a strength of 2 ...

The Magnificent jQuery Widget Factory's _trigger Instance

When utilizing the _trigger function to initiate events, I often come across a recurring issue that I struggle to fully comprehend. The problem arises when there are multiple instances of my widget on the same page. In such cases, the most recently instan ...

Having trouble with shipit.js deployment: Error encountered - git checkout undefined

I have been using shipit.js to deploy my nodejs application on an Ubuntu 16.04 server successfully. However, I recently encountered the following error: ./node_modules/shipit-cli/bin/shipit production deploy start Running 'deploy:init' task... ...

How can data be passed from a directive to a controller in Angular?

I am currently working on implementing a directive pagination feature and I need to pass the current page number from the directive to a controller in order to run a specific function with this argument. However, I keep getting an 'undefined' err ...

What is the best way to indicate the selected item in the Menu List using Material UI React?

I am attempting to dynamically style the menu list items by toggling the selected prop between true and false. In order to achieve this, I am utilizing the onClick method to capture the event.target.name, update the state of the corresponding value associ ...

Scouring the web with Cheerio to extract various information from Twitter

Just starting out with Web Scraping, using Axios to fetch the URL and Cheerio to access the data. Trying to scrape my Twitter account for the number of followers by inspecting the element holding that info, but not getting any results. Attempting to exec ...