Search code examples
javascriptasynchronouspromisechaining

Resolving promises without passing through variables


I am learning about using promises and am trying to use functional programming to achieve code modularity. My issue is that as I progress through the then() chain that I am passing parameters through intermediary then() calls for later functions to use.

This feels unnecessary and I think I am missing the forest for the trees.

function getSession(user, pass) {
    return new Promise((resolve) => {
        // do something with user and pass
        resolve(session)
    })
}


function getAccount(session) {
    return new Promise((resolve) => {
        // do something with session - pass through session
        resolve([session, account])
    })
}

function doThing(session, account) {
    return new Promise((resolve) => {
        // do something with account - pass through session
        resolve([session, thing])
    })
}

function doOtherThing(session, thing) {
    return new Promise((resolve) => {
        // do something with session and thing
        resolve(otherThing)
    })
}

let example = getSession(user, pass).then(getAccount).then(doThing).then(doOtherThing)

So for example, doThing() is passed session and account but only does something to account. However, since doOtherThing() requires session, I pass through the session instance so it can be used by that function.

So to eliminate passing through these extra variables I want to do something like

function getAccount(session) {
    return new Promise((resolve) => {
        // do something with session
        resolve(account)
    })
}

function doThing(account) {
    return new Promise((resolve) => {
        // do something with account
        resolve(thing)
    })
}

let session = getSession(user, pass)
let thing = getSession(user, pass).then(getAccount).then(doThing)
let example = doOtherThing(session, thing)

As you can see, most of these functions return a promise so I can improve code modularity by chaining elsewhere. As such the session and thing variables are assigned promises.

However in this case, I just want to resolve both promises in session and thing to then be used in doOtherThing(session, thing)

I tried something like

let session = getSession(user, pass).resolve()
let thing = getSession(user, pass).then(getAccount).then(doThing).resolve()

and

let example = doOtherThing(session.resolve(), thing.resolve())

but I get resolve is not a function as an error.

Also I know

let session = getSession(user, pass)
let thing = getSession(user, pass).then(getAccount).doThing(account)
let example = doOtherThing(session, thing)

doesn't make sense since the promises in both variables need to be resolved before passing them to doOtherThing() but I am drawing a blank as to how to do this - so this is more pseudo code showing that I don't want to pass through session

I have looked at this question but I don't think I am trying to do the same thing.


Solution

  • After looking at another answer, it seems the cleanest and most readable way to do this is using async

    function getAccount(session) {
        return new Promise((resolve) => {
            // do something with session
            resolve(account)
        })
    }
    
    function doThing(account) {
        return new Promise((resolve) => {
            // do something with account
            resolve(thing)
        })
    }
    
    const main = async () => {
        let session = await getSession(user, pass)
        let account = await getAccount(session)
        let thing = await doThing(account)
        let otherThing = await doOtherThing(session, account)
    
        return(otherthing)
    }
    
    let otherThingResult = main()
    

    This allows the promises to be executed in a familiar synchronous code style and gives a number of advantages;

    1. Variables do not need to be passed through 'chained promises' meaning the results from these resolved promises can be single variables rather than an array containing the desired variable and the passed through variables
    2. Which in turn allows 'chained' promise function parameters to accept individual variables rather than using destructuring of arrays increasing reusability of code
    3. The use of Promise.all() in other areas of code now hints more at its original functionality of executing an array of unrelated promises asynchronously
    4. Code indentation remains low and readability greatly improves