Zanko Zanko - 4 months ago 11
Javascript Question

Flattening promise chain with readable function name

I saw promise implementation in Handling multiple catches in promise chain which produce a very readable chain

return validateInput
.then(checkLoginPermission)
.then(checkDisableUser)
.then(changePassword);


However, in order to do this each function needs to return a value instead of a Promise? Since Promise can resolves to either value or a Promise so this is not a problem. My goal is to turn every function to have readable clear logic as such.

The problem occurs when trying to unwind the nested promise function

return validateInput
.then(function(resultA) {
return checkLoginPermission
.then (function(resultB) {
// Do something with resultA
})
});


Imagine the original implementation involves accessing the value from previous promise. With nested promise, it is easily achievable. But with flatten chain, I would need to break up each function like this

function validateInput = function (resultA ) {
return Promise.resolve({resultA : resultA, resultB :
}
function checkLoginPermission = function (mix ) {
let resultA = mix.resultA;
let resultB = mix.resultB
//Do something with resultA
...
}


This is worse when the last function in the chain rely on something from the very beginning. That means the value have to be passed down from the beginning of the chain even if it was not used.

So am I accidentally stepping on some kind of anti-pattern that might affect performance? How else can I achieve good readability without all these hassles?

Answer Source

This is actually where async and await come in. It's good when you need results across multiple asynchronous calls/promises to be in scope. If you can use that, I'd say try it.

async function foo () {
    const input = await validateInput()
    const hasPermission = await checkLoginPermission(input)
    const result = await checkDisableUser(hasPermission)
    return await changePassword(result)
}

Just pass the variables into what function as they need to be. Just showing an example there. I was also a bit unsure of how you're setting validateInput, i think you need to put await infront of the function call itself.

If you cannot use async/await, I usually go with your 2nd code snippet, or define the higher scope variables ontop:

let resultA
return validateInput
   .then(function(result) {
        resultA = result
        return checkLoginPermission
           .then (function(resultB) {
               // Do something with resultA
           })
   });