照片由Brendan Church在Unsplash拍摄
如果你正在开发一个应用,你可能已经被诸如 REST、GraphQL、gRPC 和 tRPC 等术语轰炸。每一个都声称能提供更好的性能、灵活性和简洁性。但哪一个才是 正确 的选择呢?
在这篇文章中,我们将分解每个API协议,看看它们的优缺点和适用场景,让你能做出明智的选择。提示一下:没有“一招鲜吃遍天”的解决方案,但我们会帮你找到最适合你项目的选择。
REST:老可靠?REST(表述性状态传递)是最常用的API设计风格。它以HTTP为基础,并利用标准方法如GET
、POST
和PUT
进行操作,在客户端和服务器之间传递信息。
这里有一个简单的REST示例,使用Express.js作为服务器端和fetch
作为客户端。
Express.js 服务器
// 服务器正在端口3000上运行
const express = require('express');
const app = express();
app.get('/api/users', (req, res) => {
res.json([{ id: 1, name: 'John Doe' }]);
});
app.listen(3000, () => console.log('服务器正在端口3000上运行'));
// 前端
fetch('http://localhost:3000/api/users')
.then(response => response.json())
.then(data => console.log('控制台输出:', data));
好处:
- 简单,易于实现
- 被所有现代工具很好地支持
- 在大多数应用程序中表现良好
不足:
- 数据抓取不当
- 可能需要多次请求才能获取相关资源
GraphQL赋予客户端查询所需精确数据的能力,而且不多。不再需要多个接口,你只需要一个,并且客户端定义响应的格式。
这里有一个使用Apollo的客户端和服务器上的简单GraphQL示例:
服务器:阿波罗服务器
// 服务器(服务端)
const { ApolloServer, gql } = require('apollo-server');
const typeDefs = gql`
type User {
id: Int
name: String
}
type Query {
users: [User]
}
`;
const resolvers = {
Query: {
users: () => [{ id: 1, name: 'John Doe' }]
}
};
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => {
console.log(`服务已启动,访问地址为 ${url}`);
});
// 客户端
import { gql, ApolloClient, InMemoryCache } from '@apollo/client';
const client = new ApolloClient({
uri: 'http://localhost:4000/',
cache: new InMemoryCache()
});
client
.query({
query: gql`
{
users {
id
name
}
}
`,
})
.then(result => console.log('查询结果:', result.data));
好的地方有:
- 更高效的查询,仅获取你需要的数据
- 在复杂的应用中减少网络请求
- 非常适合前端主导的应用程序
毛病:
- 对简单的API来说可能过于繁琐
- 新手的学习曲线较陡
当性能和低延迟至关重要时,gRPC非常理想。基于 HTTP/2,它支持双向流,非常适合高性能场景,例如微服务和实时应用。
这里有一个使用 Node.js 编写的 gRPC 服务器和客户端的例子:
使用 Node.js 的 gRPC 服务器
syntax = "proto3";
// 获取用户的请求服务
service UserService {
// 获取用户信息
rpc GetUser (UserRequest) returns (UserResponse);
}
// 用户请求消息,包含用户ID
message UserRequest {
int32 id = 1;
}
// 用户响应消息,包含用户ID和名字
message UserResponse {
int32 id = 1;
string name = 2;
}
// 服务端
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('user.proto');
const userProto = grpc.loadPackageDefinition(packageDefinition).UserService;
const server = new grpc.Server(); // 创建一个新的 gRPC 服务器实例
server.addService(userProto.service, {
GetUser: (call, callback) => {
callback(null, { id: call.request.id, name: 'John Doe' }); // 这里返回的名字是固定的 'John Doe'
},
});
server.bindAsync('localhost:50051', grpc.ServerCredentials.createInsecure(), () => { // 创建不安全的连接
server.start();
});
// 客户端
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('user.proto');
const userProto = grpc.loadPackageDefinition(packageDefinition).UserService;
const client = new userProto('localhost:50051', grpc.credentials.createInsecure()); // 创建不安全的连接
client.GetUser({ id: 1 }, (error, response) => {
console.log(response); // 控制台输出
});
好处:,
- 快速高效,非常适合微服务应用。
- 支持实时数据流处理。
- 通信具有强类型特性。
不足:
- 相比 REST 或 GraphQL,设置起来更复杂
- 没有基于 JSON 的 API 那么易于阅读
tRPC:既类型安全又轻量级
tRPC 让你无需模式或样板代码就能构建完全类型安全的 API,与 TypeScript 的无缝集成使其非常适合小型到中型的 TypeScript 项目。
这里有一个使用tRPC的快速示例,比如:
服务器:tRPC
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
const t = initTRPC.create();
const appRouter = t.router({
getUser: t.procedure.query(() => { // 查询用户信息
return { id: 1, name: 'John Doe' };
}),
});
const server = createHTTPServer({ router: appRouter }); // 服务器端代码
server.listen(3000);
// 客户端代码
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
const client = createTRPCProxyClient({
links: [httpBatchLink({ url: 'http://localhost:3000' })],
});
// 函数 fetchUser 用于异步获取用户数据并打印到控制台
async function fetchUser() {
const user = await client.getUser.query();
console.log(user);
}
// 调用 fetchUser 函数以获取用户数据
fetchUser();
好处呢?
- 端到端类型安全
- 无需手动定义API模式
- 对TypeScript项目几乎无额外开销
不足之处:
- 仅适用于 TypeScript 生态圈
- 与其它解决方案相比,相对不够成熟和普及
还是不确定吗?这里告诉你什么时候用哪个。
- REST :当你需要简单性或易用性,或者在构建传统API时。
- GraphQL :当你的前端应用需要灵活高效的数据查询时。
- gRPC :当性能至关重要时,且你在构建微服务或实时应用时。
- tRPC :当你在TypeScript环境中需要端到端的类型安全性时。
其实,实际上没有一种协议可以满足所有情况。您的API策略需要符合项目需求。选择要明智!
所以,你常用的 API 方法是哪个?你试过新兴的 tRPC 技术吗?下面评论区里聊聊吧!👇
直接了当 🚀感谢您加入__In Plain English_社区!在您离开前,
- 记得点赞并关注作者 ️👏️
- 关注我们: X | LinkedIn | YouTube | Discord | 简报 | 播客节目
- 免费在Differ上创建一个由AI驱动的博客。
- 更多精彩内容请访问 PlainEnglish.io