You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Stampit.js入门开发者求助:视图与Rest API服务实现及日志优化

你的Stamp + REST API实现方向分析与日志优化建议

首先,先给你的实现方向点个赞!你完全踩中了Stamp编程的核心思想——组合式关注点分离:

  • 把HasHttpClient、HasApiVersion、HasUrl这些通用能力拆成独立Stamp,
  • 再通过compose组合出UseRestApi基础REST能力,
  • 接着扩展WithGetOperation这类HTTP方法封装,
  • 最后落地到CustomerRestApi业务专属API。
    这种分层复用的思路非常符合Stamp的设计哲学,后续要加POST/PUT操作、其他业务API(比如OrderRestApi)都会非常方便,方向完全正确。

接下来解决你提到的日志相关问题:

1. 简化日志器注入:创建可复用的HasLogger Stamp

你现在每个Stamp都手动调用createLogger确实繁琐,我们可以把日志能力封装成一个独立的Stamp,让其他Stamp直接组合复用,自动注入带前缀的日志器:

import {compose} from '@stamp/it';
import ArgOverProp from '@stamp/arg-over-prop';

// 封装通用日志能力的Stamp
const HasLogger = ArgOverProp.argOverProp('loggerName').init([
  function () {
    // 统一创建带前缀的多级别日志方法
    const prefix = `[${this.loggerName}]`;
    this.log = (...args) => console.log(prefix, ...args);
    this.warn = (...args) => console.warn(prefix, ...args);
    this.error = (...args) => console.error(prefix, ...args);
  }
]);

2. 在业务Stamp中复用HasLogger

现在只需要在需要日志的Stamp里组合HasLogger,并传入对应的loggerName即可,不用再重复写createLogger:

优化后的UseRestApi

const UseRestApi = compose(HasHttpClient, HasApiVersion, HasUrl, HasLogger).init([
  function () {
    this.getUrl = template(this.url);
  }
]).methods({
  query: function query(method, {params, headers, body}) {
    const {apiVersion} = this;
    const q = {
      baseURL: this.getUrl({apiVersion}),
      method,
      ...params != null && {params},
      ...headers != null && {headers},
      ...body != null && {body}
    };
    this.log('request config:', q); // 直接用注入的log方法
    return q;
  }
});

优化后的WithGetOperation

const WithGetOperation = compose(UseRestApi, HasLogger).methods({
  'get': function get ({params}) {
    const q = this.query('get', {headers: {'Accept': 'application/json'}, params});
    this.log('getting data'); // 直接用注入的log方法
    return this.httpClient(q);
  }
});

优化后的CustomerRestApi

const CustomerRestApi = compose(WithGetOperation, HasLogger).methods({
  all: function all() {
    this.log('get all customers'); // 直接用注入的log方法
    return this.get({params: {page: 1, limit: 15}});
  }
});

// 创建实例时传入对应的loggerName
const customerProvider = CustomerRestApi({
  url: 'http://sample.com/<%=apiVersion%>/customers',
  apiVersion: 'v1',
  httpClient: function(config) {
    return Promise.resolve({
      status: 200,
      config
    });
  },
  loggerName: 'CustomerRestApi' // 传入日志前缀名称
});

3. 额外优化建议

  • 如果需要全局统一日志格式(比如加上时间戳),可以直接在HasLogger的init里修改日志方法的实现,所有组合了HasLogger的Stamp都会自动生效,不需要逐个修改。
  • 可以把HasLogger的日志方法做成可配置的(比如允许传入自定义日志函数),进一步提升灵活性:
    const HasLogger = compose(
      ArgOverProp.argOverProp('loggerName'),
      ArgOverProp.argOverProp('loggerImpl', {default: console})
    ).init([
      function () {
        const prefix = `[${this.loggerName}]`;
        this.log = (...args) => this.loggerImpl.log(prefix, ...args);
        this.warn = (...args) => this.loggerImpl.warn(prefix, ...args);
        this.error = (...args) => this.loggerImpl.error(prefix, ...args);
      }
    ]);
    
    这样如果后续要替换成第三方日志库(比如winston),只需要传入loggerImpl参数即可。

内容的提问来源于stack exchange,提问作者Sté

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:40:44