2

I have an API when triggered it sent 2 HTTP Get Requests

I want to get the response from the 1st Get Request and store it in a variable

so I can send it with the response of the 2nd Get Request. What is the best way to achieve it

Here is what I tried to do

    dummy.get("/api/dummy/memberProfileStats", isAuthenticated, (req, res) => {
    const userId = res.locals.user
    const memberProfileStatsURL = `/api/reports/users/${userId}/general`
    const memberLastLoginURL = `/api/users/${userId}/lastlogin`
    getRequest(memberLastLoginURL)
        .then(response => {
            let lastLoginTime = response.data.result
        })
        .catch(errorMessage => {
            console.log( 'Member Last Login API ERROR: ' + errorMessage)
            res.json(errorMessage)
        });
    getRequest(memberProfileStatsURL)
        .then(response => {
            let stats = response.data.result
            let pointsRank = [150, 500, 1000, 2000, 3500, 5000, 5500]
            let totalPoints = stats.totalPoints
            res.json({
                data: {
                    totalPoints: stats.totalPoints,
                    totalPointsRedeemed: stats.totalPointsRedeemed,
                    availablePoints: (stats.totalPoints - stats.totalPointsRedeemed),
                    totalSessionTime: secondsToHm(stats.totalSessionTime), //convert sessionTime seconds to hours
                    loginsCount: stats.totalSessions,
                    rank: rank(totalPoints, pointsRank),
                    createdTime: stats.created,
                    lastLoginTime: lastLoginTime,
                },
                result: response.data.httpStatusCode
            })
        })
        .catch(errorMessage => {
            res.json(errorMessage)
        });
})

But i get lastLoginTime is not defined

2

3 Answers 3

4

If you want the request to run in parallel, you can start them both and then wait for both of them with Promise.all. Then, when both are done, use the results from both of them to send the response:

dummy.get("/api/dummy/memberProfileStats", isAuthenticated, (req, res) => {
    const userId = res.locals.user
    const memberProfileStatsURL = `/api/reports/users/${userId}/general`
    const memberLastLoginURL = `/api/users/${userId}/lastlogin`
    // *** Start the requests in parallel
    Promise.all([
        getRequest(memberLastLoginURL)
            .then(response => {
                return response.data.result
            }),
        getRequest(memberProfileStatsURL)
            .then(response => {
                return response.data.result // *** If this is a common thing, consider a wrapper
            })                              //     function for `getRequest` so we don't have to
    ])                                      //     re-write this fulfillment handler repeatedly
    .then(([lastLoginTime, memberStats]) => {
        // *** Both are done, send response
        let pointsRank = [150, 500, 1000, 2000, 3500, 5000, 5500]
        let totalPoints = memberStats.totalPoints
        res.json({
            data: {
                totalPoints: memberStats.totalPoints,
                totalPointsRedeemed: memberStats.totalPointsRedeemed,
                availablePoints: (memberStats.totalPoints - memberStats.totalPointsRedeemed),
                totalSessionTime: secondsToHm(memberStats.totalSessionTime), //convert sessionTime seconds to hours
                loginsCount: memberStats.totalSessions,
                rank: rank(totalPoints, pointsRank),
                createdTime: memberStats.created,
                lastLoginTime: lastLoginTime,
            },
            result: 200 // *** Presumably this is 200 (or 200 is close enough), since this is a successful response
        })
    })
    .catch(errorMessage => {
        console.log( 'You'll want to update this error message: ' + errorMessage)
        res.json(errorMessage)
    })
})

Note that Promise.all's promise gets fulfilled with an array of the results in the same order as the promises fed into it.


Note that in the above it's sending 200, specifically, instead of response.data.httpStatusCode for the result. But if you really need the response.data.httpStatusCode from the memberProfileStatsURL call, you can pass it along to the final fulfillment handler like this:

dummy.get("/api/dummy/memberProfileStats", isAuthenticated, (req, res) => {
    const userId = res.locals.user
    const memberProfileStatsURL = `/api/reports/users/${userId}/general`
    const memberLastLoginURL = `/api/users/${userId}/lastlogin`
    // *** Start the requests in parallel
    Promise.all([
        getRequest(memberLastLoginURL)
            .then(response => {
                return response.data.result
            }),
        getRequest(memberProfileStatsURL)
            .then(response => {
                return {memberStats: response.data.result, httpStatusCode: response.data.httpStatusCode};
            })
    ])
    .then(([lastLoginTime, {memberStats, httpStatusCode}]) => {
        // *** Both are done, send response
        let pointsRank = [150, 500, 1000, 2000, 3500, 5000, 5500]
        let totalPoints = memberStats.totalPoints
        res.json({
            data: {
                totalPoints: memberStats.totalPoints,
                totalPointsRedeemed: memberStats.totalPointsRedeemed,
                availablePoints: (memberStats.totalPoints - memberStats.totalPointsRedeemed),
                totalSessionTime: secondsToHm(memberStats.totalSessionTime), //convert sessionTime seconds to hours
                loginsCount: memberStats.totalSessions,
                rank: rank(totalPoints, pointsRank),
                createdTime: memberStats.created,
                lastLoginTime: lastLoginTime,
            },
            result: httpStatusCode
        })
    })
    .catch(errorMessage => {
        console.log( 'You'll want to update this error message: ' + errorMessage)
        res.json(errorMessage)
    })
})
Sign up to request clarification or add additional context in comments.

10 Comments

I get try is expected when i used your code it have syntax error
@mohamedadel - I was missing a closing ) on the parameter list of the fulfillment (then) handler on the Promise.all promise, I've fixed it. It also had an extra [ in it! Sloppy of me...
@mohamedadel - Ah, I missed you were using that. Basically, just pass it from the relevant fulfillment handler to that handler. But surely the status code is 200? After all, this is a successfully-completed response...
@mohamedadel - No worries! I added a version that would use the httpStatusCode from the memberProfileStatsURL call, just in case you needed it. Happy coding!
@mohamedadel - You follow the same pattern (if you want it in parallel with the others), add it as a third entry in the array passed to Promise.all, and then add a third entry to the array destructuring in the fulfillment handler on the promise. See the MDN link above for more on Promise.all. If you wanted the request to wait and be done after one of the others, you'd put it in the fulfillment handler for the request you want it to wait for. This answer may also help.
|
1

First of all you are creating your variable inside the promise so the other promise can't read the value. Second you need to wait to the response.

dummy.get("/api/dummy/memberProfileStats", isAuthenticated, async (req, res) => {
    const userId = res.locals.user
    const memberProfileStatsURL = `/api/reports/users/${userId}/general`
    const memberLastLoginURL = `/api/users/${userId}/lastlogin`
    let lastLoginTime = await getRequest(memberLastLoginURL)
        .then(response => {
            return response.data.result
        })
        .catch(errorMessage => {
            console.log( 'Member Last Login API ERROR: ' + errorMessage)
            res.json(errorMessage)
        });
    getRequest(memberProfileStatsURL)
        .then(response => {
            let stats = response.data.result
            let pointsRank = [150, 500, 1000, 2000, 3500, 5000, 5500]
            let totalPoints = stats.totalPoints
            res.json({
                data: {
                    totalPoints: stats.totalPoints,
                    totalPointsRedeemed: stats.totalPointsRedeemed,
                    availablePoints: (stats.totalPoints - stats.totalPointsRedeemed),
                    totalSessionTime: secondsToHm(stats.totalSessionTime), //convert sessionTime seconds to hours
                    loginsCount: stats.totalSessions,
                    rank: rank(totalPoints, pointsRank),
                    createdTime: stats.created,
                    lastLoginTime: lastLoginTime,
                },
                result: response.data.httpStatusCode
            })
        })
        .catch(errorMessage => {
            res.json(errorMessage)
        });
})

Comments

1

You are trying to access lastLoginTime - the scope of which is accessible only inside your first getRequest.

Since you want to use the result of your first request in your second getRequest you should do it once you get the successful response from your first getRequesy. The correct way to do this in your code is

dummy.get("/api/dummy/memberProfileStats", isAuthenticated, (req, res) => {
    const userId = res.locals.user
    const memberProfileStatsURL = `/api/reports/users/${userId}/general`
    const memberLastLoginURL = `/api/users/${userId}/lastlogin`
    getRequest(memberLastLoginURL)
        .then(response => {
            let lastLoginTime = response.data.result
            getRequest(memberProfileStatsURL)
            .then(response => {
                let stats = response.data.result
                let pointsRank = [150, 500, 1000, 2000, 3500, 5000, 5500]
                let totalPoints = stats.totalPoints
                res.json({
                    data: {
                        totalPoints: stats.totalPoints,
                        totalPointsRedeemed: stats.totalPointsRedeemed,
                        availablePoints: (stats.totalPoints - stats.totalPointsRedeemed),
                        totalSessionTime: secondsToHm(stats.totalSessionTime), //convert sessionTime seconds to hours
                        loginsCount: stats.totalSessions,
                        rank: rank(totalPoints, pointsRank),
                        createdTime: stats.created,
                        lastLoginTime: lastLoginTime,
                    },
                    result: response.data.httpStatusCode
                })
            })
            .catch(errorMessage => {
                res.json(errorMessage)
            });
        })
        .catch(errorMessage => {
            console.log( 'Member Last Login API ERROR: ' + errorMessage)
            res.json(errorMessage)
        });
})

2 Comments

Why? What did you change? How does the change help?
@T.J.Crowder Your solution is what i tried to answer. But i did not use promise.all Instead what i thought is he can use the response of the first request atleast even though his second getRequest fails. But downvoting for that is really sad :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.