为了进行API调用,我想要进行API聚合!(NestJS ✕ GraphQL)
好,现在是问题时间!
你有下图中的3个API。
如果要创建电子邮件的新会员注册功能,你会写什么样的处理?
思考时间为10秒。
嘀嘀嘀嘀嘀 (钟表声音)
是的,感谢您的考虑。
我没有准备好答案,因为没有唯一的最佳解决方法。
本文的目的是在没有唯一最优解的情况下,与大家分享我的想法。
常见的API调用需求
我认为这次的要求如下。
-
- 我想创建用户数据
-
- 我希望在新建用户时同时生成一个令牌,以便用户可以通过登录
- 我想向用户发送常见的“感谢您注册”的电子邮件
常见模式1:编写按照所需顺序调用的方法。
func registerMember {
client.post("/users", {nickname: "田中"})
client.post("/auth", {id: "abc@yahooooo.co.jp", pw: "1234567890"})
client.post("/email", {mailAddress: "abc@yahooooo.co.jp"})
}
常见模式之二:首先,将所有内容整合到用户API中。
「生成认证令牌和发送电子邮件都是用户API的责任吧。」这是一种思考方式。
※虽然写着「边车」,但请不要太在意。
对于每种方法的挑战感
常见问题的模式之一
-
- ロジックの掛け合わせパターン分だけエンドポイントが作成されてしまう
-
- エンドポイントを別途ドキュメント管理する必要が出てくる
- 全く同じAPIの呼び出しを何度もいろんな箇所に書く必要が出てくる
常见的模式问题之二
-
- user APIの本来果たすべき「ユーザリソースの作成」以外のことも行っているため、つなぎ込み先のAPIがemailからslackに変わった途端に複雑性が一気に増す
-
- つなぎ込み先との関連性を考慮する必要があるため、user APIのインターフェースが複雑になる
- auth APIの修正をしただけなのにuser APIの修正もしなければいけなくなる
想要在本篇文章中介绍的调用模式
使用NestJS和GraphQL创建聚合API。
对于那些尚未接触过GraphQL的人来说,简单解释一下GraphQL具有以下约束:
-
- エンドポイントは「/graphql」のたった一つのみ
-
- リソースの操作はquery(パラメータ)で行う
-
- ドキュメンテーションの作成を行わなくてもコードから自動的にインターフェース(query)定義書を生成してくれる
- 厳格なスキーマ設定があるので、存在しないパラーメータや異なるデータ型は許容されない
换句话说,只需要构建查询,就可以一次性调用多个API!
mutation RegisterMember($email: String!) {
## ユーザ作成
createUser(
createUserInput: {
nickname: "田中"
}
) {
nickname
}
## 認証データ作成かつトークン返却
createAuth(
createAuthInput: {
id: $email
pw: "password"
}
) {
token
}
## メール送信
sendEmail(
sendEmailInput: {
subject: "hello"
email: $email
}
)
}
不是银弹
-
- user APIのレスポンスデータを後続のauth APIに引き継げない
-
- 単一のエンドポイントしか提供しない為、場合によってエラーハンドルが複雑になる
statusは200しか返せません
由于无法将用户API的响应数据传递给后续的auth API,所以需要调用API三次吗?
实际上并不是这样的。
只要无法将响应参数作为GraphQL上的变量接收,就可以在内部不同的方法之间传递数据。
是的,如果使用NestJS的话。
※ 不仅限于NestJS。与Rails的脚手架一样,能够自动为您提供所有东西,这是它的优点而已。
关于NestJS的Module
NestJS允许将Resolver和Service与一个Module相互关联。
解析器在MVC框架中相当于控制器。
服务在MVC中相当于模型。
由于本文讨论了API调用,因此严格来说,NestJS本身并不拥有资源,但可以通过Service(红框)来操作外部资源进行API调用。
Module之间可以互相引用。
按照下图所示。
因此,邮件解析器可以调用用户服务的方法并访问其属性。
在以下方面,NestJS ✕ GraphQL不是银弹点②:
-
- Module間の参照が増えれば増えるほど、各Service(赤枠)の変更が行いにくくなる (アプリケーションが複雑になる)
-
- 人によってはAPIに書くべきビジネスロジックをResolverやServiceに書き込んでしまう。
コード規約で回避可能ですが、意外と100%浸透させるのは難しいです。
本文总结
-
- それでもやっぱり自分はAPIを呼び出すなら、API Aggregationしたいんじゃ!
-
- 明確な最適解は無い。というか教えて下さい。お願いします。(懇願)
-
- 個人的にはBFFはブラウザから呼べた方がいいよねと思っております。
-
- なので、email送信用のGraphQL関数を作成する際はアドレスと内容を受け取ったら宛先に送れるような関数はセキュリティ的にNGです。 (迷惑メール送り放題なので)
- テレビ千鳥が好きです。
中文本地化,仅需要一个选项:
采用公关策略