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

如何减少TypeScript搭建Node gRPC服务时请求响应处理的冗余代码

可行的优化方案

1. 实现通用消息实例转换工具

你可以基于所有生成的jspb.Message子类的公共特征,写一个泛型转换函数,一次性解决手动调用setter的冗余问题:

type Constructor<T> = new () => T;
type MessageAsObject<T extends jspb.Message> = T extends { toObject(): infer O } ? O : never;

function createMessageInstance<T extends jspb.Message>(
  MessageCls: Constructor<T>,
  data: MessageAsObject<T>
): T {
  const instance = new MessageCls();
  Object.entries(data).forEach(([key, value]) => {
    const setterName = `set${key.charAt(0).toUpperCase() + key.slice(1)}`;
    // 生成的消息类的setter都符合该命名规则,可放心调用
    (instance as any)[setterName](value);
  });
  return instance;
}

使用后原来的映射逻辑可以直接简化为:

const dogEntities = dogs.map(dogObj => createMessageInstance(DogEntity, dogObj));

2. 封装通用RPC处理器模板

针对CRUD类的固定逻辑(单查询、列表查询、新增、更新、删除),你可以提前封装对应高阶函数,直接复用重复的请求响应处理逻辑,比如针对服务端流的列表查询封装:

import * as grpc from '@grpc/grpc-js';
import { Empty } from './generated/proto/common_pb';

type ListHandlerOptions<Res extends jspb.Message, Entity> = {
  ResponseClass: Constructor<Res>,
  fetchData: () => Promise<Entity[]>
}

function createServerStreamListHandler<Res extends jspb.Message, Entity>(
  opts: ListHandlerOptions<Res, Entity>
) {
  return async (call: grpc.ServerWritableStream<Empty, Res>) => {
    const dataList = await opts.fetchData();
    dataList.forEach(item => {
      const resInstance = createMessageInstance(opts.ResponseClass, item as any);
      call.write(resInstance);
    });
    call.end();
  }
}

封装完成后,你的getAllDogs方法可以直接简化为一行声明:

getAllDogs = createServerStreamListHandler({
  ResponseClass: DogEntity,
  fetchData: () => dogService.repo.findAll()
})

3. 更换代码生成实现

如果不想依赖grpc_tools_node_protoc生成的基于setter的消息类,可以更换为支持直接使用POJO对象的protobuf TypeScript生成方案,生成的消息直接为普通TS类型,不需要实例化和调用setter,从根源消除转换冗余,处理器里可以直接将业务对象作为响应返回。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:39:02