farrow-js / farrow

A Type-Friendly Web Framework for Node.js
https://www.farrowjs.com
MIT License
768 stars 37 forks source link

Feature Request(farrow-pipeline): Custom callback of Counter #126

Closed tqma113 closed 2 years ago

tqma113 commented 2 years ago

Support to custom callback of Counter:

For now, it is stable:

...

const createCurrentCounter = (hooks: Hooks, onLast?: (input: I) => O, onLastWithContext?: boolean) => {
    return createCounter<I, O>((index, input, next) => {
      if (index >= middlewares.length) {
        if (onLast) {
          if (onLastWithContext) {
            return runHooks(() => onLast(input), hooks)
          }
          return onLast(input)
        }
        throw new Error(`Expect returning a value, but all middlewares just calling next()`)
      }

      const middleware = middlewares[index]
      const result = runHooks(() => middleware(input, next), hooks)

      return result
    })
  }
...

Expect:

const customCounterCallback = () => { /** ... */ }
const pipeline = createPipeline(customCounterCallback)

for more way to run middlewares.

const pipeline = createPipeline<number, number>()

const foo = (a: number) => a+1
const bar = (a: number) => a*2
const baz = (a: number) => a**2
pipeline.use(foo)
pipeline.use(foo)
pipeline.use(foo)

pipeline.run(1) // 2
// only run foo

If I can custom callback of Counter:

const pipeline = createPipeline<number, number>((index, input, next) => {
  if (index >= middlewares.length) {
    return input;
  }

  return runHooks(() => next(middlewares[index](input)), hooks);
})

...

pipeline.run(1) // 16
// run: foo -> bar -> baz
Lucifier129 commented 2 years ago

It's hard to see the necessity to support custom counter callback in the use-case you shown above.

Just introduce a helper function for auto-calling next.

const autoPass = (f) => (input, next) => next(f(input))

const pipeline = createPipeline<number, number>()

const foo = (a: number) => a+1
const bar = (a: number) => a*2
const baz = (a: number) => a**2

pipeline.use(autoPass(foo))
pipeline.use(autoPass(bar))
pipeline.use(autoPass(baz))

pipeline.run(1) // 16

Or introduce createAutoPassPipeline() for that.

const createAutoPassPipeline = () => {
  const pipeline = createPipeline()
  return  {
    use: f => {
      pipeline.use((input, next) => next(f(input))
    }
  }
}
Lucifier129 commented 2 years ago

Another concern is that if we expose the counter under farrow-pipeline, the user almost can do everything even breaking the semantic of pipeline