Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to pipe functions, when a promise in the promise in the middle checks authorization?

i'm trying to compose some functions together:

compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));

checkAuthorization returns a promise that check if a user is authorized. buildParams receives someRequestData, and pipes the result to searchItem.

    checkAuthorization()
      .then(() => {
            compose(
                searchItem,
                buildParams
            )(someRequestData)
    }, (e) => {
       handleError(e)
    })

I think it's OK, but I wish to have a more elegant look for readability, something like:

    compose(
      searchItem,
      checkAuthorization
      buildParams
    )(someRequestData)

so what will happen is: 1) build params 2) checkAuth 3) search item

Any suggestions?

like image 509
Chen Avatar asked Jan 27 '26 10:01

Chen


2 Answers

No, that's not possible, since checkAuthorisation does not receive and pass through the params. And even if you would rewrite it to do that, it still would be weird and a reader would assume that you're building the params whose authorisation should be checked. So don't do that - you have a non-linear flow, and trying to force it into some linear composition is no good.

Btw, I would recommend to avoid compose when you're calling the function immediately anyway:

checkAuthorization().then(() =>
  searchItem(buildParams(someRequestData))
, e =>
   handleError(e)
);

or maybe

checkAuthorization().then( compose(searchItem, buildParams, ()=>someRequestData)
                         , handleError ); //                ^^^^ "const"
like image 138
Bergi Avatar answered Jan 29 '26 10:01

Bergi


Here's a composer to handle both sync functions and Promises. Looks like it works correctly maintaining the order:

// Async pipe try. Pass functions left to right
const pipePromises = (...fns) => x => fns.reduce((p, fn) => p.then(fn), Promise.resolve(x));
  
// functions for the test
const me = x => new Promise(function(resolve, reject) {
  setTimeout(() => resolve(x), 10)
})

const double = x => new Promise(function(resolve, reject) {
  setTimeout(() => resolve(x * 2), 30)
})

const inc = x => new Promise(function(resolve, reject) {
  setTimeout(() => resolve(x + 1), 400)
})

const log = x => { console.log('log: ', x); return x }

const syncTriple = x => x * 3; // sync function

// let's call our chain
pipePromises( 
  me, log, // 3
  double, log, // 6
  syncTriple, log, // 18 -- SYNC
  inc, log, // 19
  double, log, // 38
  inc, log, // 39
  syncTriple, log, // 117 -- SYNC
  inc, log // 118
)(3) // 3
like image 29
Egor Stambakio Avatar answered Jan 29 '26 12:01

Egor Stambakio