0

抱歉标题太长了...

我正在用 gRPC 和 typescript 实现一个简单的 crud 小系统,我的问题是:自动生成的文件为我的每个参数创建一个类和一个类型protoFile,例如:UserId 参数生成一个带有 getUserId 等的类,以及一个带有UserId 的类型。

问题是当我尝试在我的方法中使用该方法时client,打字稿需要一个类作为参数而不是类型。

所以而不是getUsersById({id: 1}, callback)......它要求我做getUsersById(new UserId)

用户原型:

syntax = "proto3";

package userServicePKG;

message User {
    int32 id = 1;
    string name = 2;
    int32 age = 3;
}

message UserId {
    int32 id = 1;
}

service UserService{
    rpc getUserById (UserId) returns (User);
}

UserServiceClientPb.ts (Protobuf 生成) - 函数定义

methodInfogetUserById = new grpcWeb.AbstractClientBase.MethodInfo(
    User,
    (request: UserId) => {
      return request.serializeBinary();
    },
    User.deserializeBinary
  );

  getUserById(
    request: UserId,
    metadata: grpcWeb.Metadata | null): Promise<User>;

  getUserById(
    request: UserId,
    metadata: grpcWeb.Metadata | null,
    callback: (err: grpcWeb.Error,
               response: User) => void): grpcWeb.ClientReadableStream<User>;

  getUserById(
    request: UserId,
    metadata: grpcWeb.Metadata | null,
    callback?: (err: grpcWeb.Error,
               response: User) => void) {
    if (callback !== undefined) {
      return this.client_.rpcCall(
        new URL('/userServicePKG.UserService/getUserById', this.hostname_).toString(),
        request,
        metadata || {},
        this.methodInfogetUserById,
        callback);
    }
    return this.client_.unaryCall(
    this.hostname_ +
      '/userServicePKG.UserService/getUserById',
    request,
    metadata || {},
    this.methodInfogetUserById);
  }

user_pb.d.ts (Protobuf Generated) - 定义类型和类:

export class UserId extends jspb.Message {
  getId(): number;
  setId(value: number): UserId;

  serializeBinary(): Uint8Array;
  toObject(includeInstance?: boolean): UserId.AsObject;
  static toObject(includeInstance: boolean, msg: UserId): UserId.AsObject;
  static serializeBinaryToWriter(message: UserId, writer: jspb.BinaryWriter): void;
  static deserializeBinary(bytes: Uint8Array): UserId;
  static deserializeBinaryFromReader(message: UserId, reader: jspb.BinaryReader): UserId;
}

export namespace UserId {
  export type AsObject = {
    id: number,
  }
}

客户端.Vue:

const client = new UserServiceClient('http://localhost:5001', null, null);

let userId = { id:1 };
client.getUserById(userId, function (error: grpcWeb.Error, response: any) {
     //do something
});

参数 userId 引发以下错误:

'{ id: number; 类型的参数 }' 不可分配给“UserId”类型的参数。键入'{ id:数字;}' 缺少来自“UserId”类型的以下属性:getId、setId、serializeBinary、toObject 和另外 8 个。Vetur(2345)

在我看来,打字稿推断出getUserById第一个参数是类型Class UserId而不是来自命名空间 UserId的类型。

有什么我可以做的吗?由于它是自动生成的,我觉得它应该正确解释吗?我在搞砸别的事情吗?我是 gRPC 的新手,所以我可能做错了什么。

提前致谢!

4

1 回答 1

2

消息UserId作为 JavaScript 类生成。你必须提供这个类的一个实例,实际上没有任何替代方案,至少不是由 protoc-gen-grpc-web 生成的代码。

有一些基于 TypeScript 的替代代码生成器不需要您使用类。ts-proto 和 protobuf-ts 使用简单的接口而不是类来表示消息。(我是protobuf-ts的作者)。

例如,protobuf-ts 从你的 user.proto 生成代码,可以这样使用:

// gRPC-web provided by @protobuf-ts/grpcweb-transport
const transport = new GrpcWebFetchTransport("http://localhost:5001");

const client = new UserServiceClient(transport);

const {response} = await client.getUserById({id: 123});

console.log(
    response.id,
    response.name,
    response.age
);

我认为 ts-proto 前段时间也得到了 grpc-web 支持。也许试一试,看看你是否更喜欢生成的代码。

于 2020-12-16T20:47:23.090 回答