Skip to content

实战与最佳实践

实战案例

案例 1:数据验证管道

构建一个灵活的验证器:

typescript
type ValidationResult<T> =
  | { success: true; data: T }
  | { success: false; errors: string[] }

// 验证器工厂
const createValidator = <T>() => {
  const pipeline = createPipeline<any, ValidationResult<T>>()
  const rules: Array<{
    name: string
    check: (data: any) => boolean
    message: string
  }> = []

  return {
    // 添加验证规则
    rule(name: string, check: (data: any) => boolean, message: string) {
      rules.push({ name, check, message })

      pipeline.use((data, next) => {
        const rule = rules[rules.length - 1]

        if (!rule.check(data)) {
          return {
            success: false,
            errors: [`${rule.name}: ${rule.message}`]
          }
        }

        return next(data)
      })

      return this
    },

    // 执行验证
    validate(data: any): ValidationResult<T> {
      return pipeline.run(data, {
        onLast: (data) => ({ success: true, data })
      })
    }
  }
}

// 使用
const userValidator = createValidator<User>()
  .rule('email',
    (d) => /@/.test(d.email),
    '邮箱格式不正确'
  )
  .rule('age',
    (d) => d.age >= 18,
    '必须年满 18 岁'
  )
  .rule('password',
    (d) => d.password.length >= 8,
    '密码至少 8 位'
  )

const result = userValidator.validate({
  email: 'test@example.com',
  age: 25,
  password: 'secure123'
})

if (result.success) {
  console.log('✅ 验证通过', result.data)
} else {
  console.log('❌ 验证失败', result.errors)
}

案例 2:状态机

用 Pipeline 实现一个简单的状态机:

typescript
import { createPipeline, createContext } from 'farrow-pipeline'

type State = 'idle' | 'loading' | 'success' | 'error'
type Event =
  | { type: 'FETCH' }
  | { type: 'SUCCESS'; data: any }
  | { type: 'FAIL'; error: string }
  | { type: 'RESET' }

const StateContext = createContext<State>('idle')

const stateMachine = createPipeline<Event, State>()

stateMachine.use((event, next) => {
  const currentState = StateContext.get()

  // 状态转换逻辑
  switch (event.type) {
    case 'FETCH':
      if (currentState === 'idle') {
        StateContext.set('loading')
      }
      break

    case 'SUCCESS':
      if (currentState === 'loading') {
        StateContext.set('success')
      }
      break

    case 'FAIL':
      if (currentState === 'loading') {
        StateContext.set('error')
      }
      break

    case 'RESET':
      StateContext.set('idle')
      break
  }

  return next(event)
})

stateMachine.use(() => {
  return StateContext.get()
})

// 使用
console.log(stateMachine.run({ type: 'FETCH' }))     // 'loading'
console.log(stateMachine.run({ type: 'SUCCESS', data: {} })) // 'success'
console.log(stateMachine.run({ type: 'RESET' }))     // 'idle'

案例 3:请求处理管道

typescript
interface Request {
  method: string
  url: string
  headers: Record<string, string>
  body?: any
}

interface Response {
  status: number
  headers: Record<string, string>
  body: any
}

const app = createAsyncPipeline<Request, Response>()

// 日志中间件
app.use((req, next) => {
  const start = Date.now()
  console.log(`→ ${req.method} ${req.url}`)

  const res = next(req)

  const duration = Date.now() - start
  console.log(`← ${res.status} (${duration}ms)`)
  return res
})

// CORS 中间件
app.use((req, next) => {
  const res = next(req)
  return {
    ...res,
    headers: {
      ...res.headers,
      'Access-Control-Allow-Origin': '*'
    }
  }
})

// 认证中间件
app.use((req, next) => {
  const token = req.headers.authorization

  if (!token) {
    return {
      status: 401,
      headers: {},
      body: { error: 'Unauthorized' }
    }
  }

  return next(req)
})

// 路由处理
app.use((req) => {
  if (req.url === '/users') {
    return {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
      body: { users: [] }
    }
  }

  return {
    status: 404,
    headers: {},
    body: { error: 'Not Found' }
  }
})

最佳实践

✅ 1. 类型优先

typescript
// ✅ 好:明确指定类型
const pipeline = createPipeline<Request, Response>()

// ❌ 不好:类型推导可能不准确
const pipeline = createPipeline()

✅ 2. 单一职责

每个中间件只做一件事:

typescript
// ✅ 好:职责清晰
pipeline
  .use(authMiddleware)
  .use(validationMiddleware)
  .use(businessLogicMiddleware)

// ❌ 不好:职责混乱
pipeline.use((req, next) => {
  // 认证 + 验证 + 业务逻辑全部混在一起
  const user = authenticate(req)
  const valid = validate(req)
  const result = processRequest(req, user)
  return result
})

✅ 3. 合理使用 Context

适合用 Context

  • 🟢 跨中间件共享的请求级数据(用户、请求 ID)
  • 🟢 需要隔离的状态

不适合用 Context

  • 🔴 全局配置(用模块变量)
  • 🔴 可以通过参数传递的数据
typescript
// ✅ 好:适合用 Context
const UserContext = createContext<User | null>(null)
const RequestIdContext = createContext<string>('')

// ❌ 不必要:用模块变量就行
const ConfigContext = createContext({ apiUrl: 'https://api.example.com' })
// 改成这样:
const API_URL = 'https://api.example.com'

✅ 4. 错误处理

在适当的层级处理错误:

typescript
// 全局错误处理中间件(放在最前面)
pipeline.use(async (input, next) => {
  try {
    return await next(input)
  } catch (error) {
    console.error('💥 出错了:', error)
    return { status: 500, error: error.message }
  }
})

// 业务逻辑可以放心抛错
pipeline.use(async (input, next) => {
  const data = await riskyOperation(input)  // 可能抛错
  return next(data)
})

✅ 5. 懒加载优化性能

typescript
// ✅ 好:懒加载重型依赖
pipeline.useLazy(async () => {
  const { heavyLib } = await import('./heavy-lib')
  return (req, next) => {
    if (needsProcessing(req)) {
      return next(heavyLib.process(req))
    }
    return next(req)
  }
})

// ❌ 不好:启动时加载
import { heavyLib } from './heavy-lib'  // 拖慢启动速度

✅ 6. 测试友好

使用 Container 注入依赖:

typescript
import { createContainer } from 'farrow-pipeline'

const DatabaseContext = createContext<Database>(realDatabase)

// 测试时注入 mock
const testContainer = createContainer({
  db: DatabaseContext.create(mockDatabase)
})

const result = pipeline.run(testInput, { container: testContainer })

✅ 7. 可复用的中间件工厂

typescript
// 中间件工厂
const createLoggerMiddleware = (options: { level: 'info' | 'debug' }) => {
  return (input: any, next: any) => {
    if (options.level === 'debug') {
      console.log('📝 输入:', input)
    }

    const result = next(input)

    console.log('📝 输出:', result)
    return result
  }
}

// 使用
pipeline.use(createLoggerMiddleware({ level: 'debug' }))

⚠️ 8. 浏览器环境不支持

typescript
// ❌ 浏览器中无法使用
import { createPipeline } from 'farrow-pipeline'  // 会报错

// ✅ 仅在 Node.js 中使用

常见陷阱

陷阱 1: 忘记调用 next

typescript
// ❌ 错误:忘记调用 next
pipeline.use((input, next) => {
  console.log('处理中...')
  // 忘记返回 next(input)
})

// ✅ 正确
pipeline.use((input, next) => {
  console.log('处理中...')
  return next(input)
})

陷阱 2: 异步中忘记 await

typescript
// ❌ 错误:忘记 await
pipeline.use(async (input, next) => {
  const result = next(input)  // 返回 Promise,但没有 await
  console.log(result)  // Promise 对象
  return result
})

// ✅ 正确
pipeline.use(async (input, next) => {
  const result = await next(input)
  console.log(result)  // 实际值
  return result
})

陷阱 3: Context 在异步中丢失

typescript
// ❌ 错误:没有启用 AsyncLocalStorage
UserContext.set(user)
await delay(1000)
const u = UserContext.get()  // undefined

// ✅ 正确:启用异步追踪
import * as asyncTracerImpl from 'farrow-pipeline/asyncTracerImpl.node'
asyncTracerImpl.enable()

下一步

恭喜你!🎉 现在你已经掌握了 farrow-pipeline 的所有核心知识。

推荐学习路径

  1. 📖 查看 完整 API 参考 - 深入了解每个 API
  2. 🌐 学习 farrow-http - 构建 HTTP 服务器
  3. 🎯 探索 farrow-schema - 类型验证

实践建议

  • 🔨 在小项目中试用 Pipeline
  • 📦 封装你的常用中间件
  • 🧪 为中间件编写单元测试

记住:好的代码就像好的管道,清晰、流畅、不漏水!🚰

这是一个第三方 Farrow 文档站 | 用 ❤️ 和 TypeScript 构建