节点API设计和重用代码

时间:2013-08-25 22:44:37

标签: javascript node.js api rest abstract

我的API有三个端点:articleswebsitesusers。每个article都与website相关联。 user也可以共享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中设计API时,这种代码重用问题必须是常见的,我想知道我是否有一个明显更好的解决方案。

我的一个想法就是让所有文章子资源(例如/users/:id/shared-articles/websites/:id/links)在内部与/links API对话,这本身就会处理操作我提到上面。那么问题是我必须在它需要的查询头/参数中使/links非常冗长,以便允许所需的不同数据库查询(例如这里演示的两个子资源端点的查询)

这里有更好的解决方案/抽象吗?

1 个答案:

答案 0 :(得分:1)

您可以创建“服务”图层。将链接操作抽象为一个完全独立的文件,并从每个路径调用它。

创建服务/ links.js:

module.exports = {
    manipulateLinks: function (response) {
        // Manipulate code
        return response
    }
}

然后在你的路线中,调用函数:

var linkservice = require('../service/links')
var response = linkservice.manipulateLinks(response)