articles
私の API には、 、websites
、およびの3 つのエンドポイントがありusers
ます。それぞれarticle
が に関連付けられていwebsite
ます。Auser
も共有できますarticles
。
私の API では、 にエンドポイントを作成しました/website/:id/articles
。articles
これは、指定された に関連付けられているデータベースを照会しますwebsite
。次に、誰が API と話しているかに基づいて、各記事のデータに対して何らかの操作を実行します (たとえば、「ユーザーはこの記事を共有しましたか?」)。
で同様のエンドポイントを作成します/users/:id/shared-articles
。このためのデータベース クエリは少し異なりますが、クエリに続く記事データに対して実行する操作は以前と同じです。
前のエンドポイントの疑似コードを次に示します。
router.get('/websites/:id/articles', function (req, res) {
articleService.find({ websiteId: req.params.id }, function (error, foundArticles) {
async.waterfall([
function (cb) {
// Manipulate foundArticles…
cb(null, manipulatedArticles)
},
function (articles, cb) {
// Manipulate articles some more…
cb(null, manipulatedArticles)
},
], function (error, articles) {
if (error) {
return res.json(error, 400)
}
res.json(articles)
})
})
})
新しいエンドポイント を作成するために/users/:id/shared-articles
、操作タスクを両方のエンドポイントで共有できる関数に抽象化し (上記のウォーターフォール)、コードの繰り返しを減らすことができます。
router.get('/websites/:id/articles', function (req, res) {
articleService.find({ websiteId: req.params.id }, function (error, foundArticles) {
manipulateArticles(foundArticles, function (articles) {
if (error) {
return res.json(error, 400)
}
res.json(articles)
})
})
})
router.get('/users/:id/shared-articles', function (req, res) {
shareActionService.find({ userId: req.params.id }, function (error, foundShareActions) {
var sharedArticleIds = { _id: { $in: _.pluck(foundShareActions, 'sharedArticleId') } }
articleService.find(sharedArticleIds, function (error, foundArticles) {
manipulateArticles(foundArticles, function (articles) {
if (error) {
return res.json(error, 400)
}
res.json(articles)
})
})
})
})
しかし、この種のコードの再利用の問題は、Node.js で API を設計する際によくあることであると考えました。ここに欠けている明らかに優れた解決策があるかどうかを知りたいです。
私が持っていた 1 つのアイデアは、記事のすべてのサブリソース (/users/:id/shared-articles
または など/websites/:id/links
) が/links
内部で API と通信するようにすることでした。問題は、/links
必要なさまざまなデータベース クエリ (ここで示した 2 つのサブリソース エンドポイントによるものなど) を許可するために、必要なクエリ ヘッダー/パラメーターを非常に冗長にする必要があることです。
ここでより良い解決策/抽象化はありますか?