#typescript #vue.js #grpc #protobuf.js
#typescript #vue.js #grpc #protobuf.js
Вопрос:
Извините за длинный заголовок…
Я реализую простую систему crud little с gRPC и typescript, моя проблема: Автоматически сгенерированный файл создает класс и тип для каждого параметра в my protoFile
, например: параметр userId генерирует класс с getUserId и т. Д. И пространство имен с типом для userId .
Проблема в том, что когда я пытаюсь использовать метод в my client
, typescript ожидает класс в качестве параметра, а не тип.
поэтому вместо 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) — определение типов и классов:
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: number; }’ отсутствуют следующие свойства из типа ‘userId’: getId, setId, serializeBinary, ToObject и еще 8.Vetur(2345)
Мне кажется, что typescript делает вывод, что getUserById
первый параметр имеет тип Class UserId
, а не тип, исходящий из пространства UserId
имен.
Могу ли я что-нибудь с этим поделать? Поскольку он был автоматически сгенерирован, я чувствую, что он должен правильно интерпретировать? Я что-то еще путаю? Я новичок в gRPC, поэтому, возможно, я делаю что-то не так.
Заранее спасибо!
Ответ №1:
Сообщение UserId
генерируется как класс JavaScript. Вы должны предоставить экземпляр этого класса, альтернативы на самом деле нет, по крайней мере, с кодом, сгенерированным protocol-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 некоторое время назад. Может быть, попробуйте один из них и посмотрите, нравится ли вам сгенерированный код лучше.
Комментарии:
1. Вы правы, моя проблема в том, что я просматривал онлайн-примеры, в которых использовался gRPC на других платформах, а не gRPC web, если вы создаете прототипы с помощью gRPC web, вам нужно создать экземпляр своего «сообщения», а затем инициировать его значения через сеттеры и использовать их через геттеры… Большое спасибо!