Performancehard

Implement compose / middleware pipeline

Implement a `compose` function (right-to-left) and a Koa/Express-style `applyMiddleware` that chains async middleware with `next()`. This is the core of most web framework middleware systems.

Asked at TikTok, Stripe

#functional programming#middleware#async#compose

Answer

// compose(f, g, h)(x) = f(g(h(x))) — right to left
function compose(...fns) {
  return (x) => fns.reduceRight((acc, fn) => fn(acc), x)
}

// pipe(f, g, h)(x) = h(g(f(x))) — left to right
const pipe = (...fns) => (x) => fns.reduce((acc, fn) => fn(acc), x)

// Usage
const double = x => x * 2
const addOne = x => x + 1
const square = x => x * x

compose(square, addOne, double)(3)  // square(addOne(double(3))) = 49
pipe(double, addOne, square)(3)     // square(addOne(double(3))) = 49

// ─────────────────────────────────────────────────────────
// Koa-style async middleware (like TikTok/Express internals)
function applyMiddleware(middlewares) {
  return function(ctx) {
    function dispatch(i) {
      if (i >= middlewares.length) return Promise.resolve()
      const middleware = middlewares[i]
      return Promise.resolve(middleware(ctx, () => dispatch(i + 1)))
    }
    return dispatch(0)
  }
}

// Usage
const logger = async (ctx, next) => {
  console.log('before', ctx.url)
  await next()
  console.log('after', ctx.url)
}
const handler = async (ctx, next) => {
  ctx.body = 'Hello'
  await next()
}
const run = applyMiddleware([logger, handler])
run({ url: '/home' })

Source: frontendinterviewhandbook.com — TikTok

Practise more Performance questions →