接口设计

  1. 创建文章
    // POST 请求:/articles
    // 请求体:
    {
      "article": {
        "title": "How to train your dragon",
        "description": "Ever wonder how?",
        "body": "You have to believe",
        "tagList": ["reactjs", "angularjs", "dragons"]
      }
    }
    
    // 响应状态码:201
    // 响应数据:
    {
      "article": {
        "_id": 123,
        "title": "How to train your dragon",
        "description": "Ever wonder how?",
        "body": "It takes a Jacobian",
        "tagList": ["dragons", "training"],
        "createdAt": "2016-02-18T03:22:56.637Z",
        "updatedAt": "2016-02-18T03:48:35.824Z"
      }
    }
    
  2. 获取文章列表
    // GET 请求:/articles
    // 请求参数(Query):_page:页码、_size:每页大小
    
    // 响应状态码:201
    // 响应数据:
    {
      "articles": [
        {
          "_id": "how-to-train-your-dragon",
          "title": "How to train your dragon",
          "description": "Ever wonder how?",
          "body": "It takes a Jacobian",
          "tagList": ["dragons", "training"],
          "createdAt": "2016-02-18T03:22:56.637Z",
          "updatedAt": "2016-02-18T03:48:35.824Z"
        },
        {
          "_id": "how-to-train-your-dragon-2",
          "title": "How to train your dragon 2",
          "description": "So toothless",
          "body": "It a dragon",
          "tagList": ["dragons", "training"],
          "createdAt": "2016-02-18T03:22:56.637Z",
          "updatedAt": "2016-02-18T03:48:35.824Z"
        }
      ],
      "articlesCount": 2
    }
    
  3. 获取单个文章
    // GET 请求:/articles/:id
    	
    // 响应状态码:201
    // 响应数据:
    {
      "article": {
        "_id": "dsa7dsa",
        "title": "How to train your dragon",
        "description": "Ever wonder how?",
        "body": "It takes a Jacobian",
        "tagList": ["dragons", "training"],
        "createdAt": "2016-02-18T03:22:56.637Z",
        "updatedAt": "2016-02-18T03:48:35.824Z"
      }
    }
    
  4. 更新文章
    // PATCH 请求:/articles/:id
    // 请求体:
    {
      "article": {
        "title": "Did you train your dragon?"
      }
    }
    
    // 响应状态码:201
    // 响应数据:
    {
      "article": {
        "_id": 123,
        "title": "How to train your dragon",
        "description": "Ever wonder how?",
        "body": "It takes a Jacobian",
        "tagList": ["dragons", "training"],
        "createdAt": "2016-02-18T03:22:56.637Z",
        "updatedAt": "2016-02-18T03:48:35.824Z"
      }
    }
    
  5. 删除文章
    // DELETE 请求:/articles/:id
    
    // 响应状态码:201
    // 响应数据:
    { }
    

接口服务实现

const express = require('express')

const { MongoClient, ObjectID } = require('mongodb')
const dbClient = new MongoClient('mongodb://localhost:27017')

const app = express()

// 配置解析请求体数据 application/json,会把解析到的请求体数据放到 req.body 中
// 注意:一定要在使用之前就挂载这个中间件
app.use(express.json())


app.get('/', (req, res) => res.send('Hello World!'))

// 创建文章
app.post('/articles', async (req, res, next) => {
  try {
    // 1. 获取客户端表单数据
    const { article } = req.body
    // 2. 数据验证
    if (!article || !article.title || !article.description || !article.body) {
      return res.status(422).json({ error: '请求参数不符合规则要求' })
    }
    // 3. 把验证通过的数据插入数据库中
    //    成功 -> 发送成功响应
    //    失败 -> 发送失败响应
    await dbClient.connect()
    const collection = dbClient.db('test').collection('articles')
    article.createdAt = new Date()
    article.updatedAt = new Date()
    const ret = await collection.insertOne(article)
    article._id = ret.insertedId
    res.status(201).json({ article })
  } catch (err) {
    // 由错误处理中间件统一处理
    next(err)
  }
})

// 获取文章列表
app.get('/articles', async (req, res, next) => {
  try {
    let { _page = 1, _size = 10 } = req.query
    _page = Number.parseInt(_page)
    _size = Number.parseInt(_size)
    await dbClient.connect()
    const collection = dbClient.db('test').collection('articles')
    const ret = await collection
      .find() // 查询数据
      .skip((_page - 1) * _size) // 跳过多少条 10 1 0 2 10 3 20 n
      .limit(_size) // 拿多少条
    const articles = await ret.toArray()
    const articlesCount = await collection.countDocuments()
    res.status(200).json({ articles, articlesCount })
  } catch (err) {
    next(err)
  }
})

// 获取单个文章
app.get('/articles/:id', async (req, res, next) => {
  try {
    await dbClient.connect()
    const collection = dbClient.db('test').collection('articles')
    const article = await collection.findOne({ _id: ObjectID(req.params.id) })
    res.status(200).json({ article })
  } catch (err) {
    next(err)
  }
})

// 更新文章
app.patch('/articles/:id', async (req, res, next) => {
  try {
    await dbClient.connect()
    const collection = dbClient.db('test').collection('articles')
    await collection.updateOne({ _id: ObjectID(req.params.id) }, { $set: req.body.article })
    // req.body.article 在更新后会被变更为更新结果的状态信息
    // 查询更新后的数据(仅匹配 _id 可以直接简写为传参)
    const article = await collection.findOne({ _id: ObjectID(req.params.id) })
    res.status(201).json({ article })
  } catch (err) {
    next(err)
  }
})

// 删除文章
app.delete('/articles/:id', async (req, res, next) => {
  try {
    await dbClient.connect()
    const collection = dbClient.db('test').collection('articles')
    await collection.deleteOne({ _id: ObjectID(req.params.id) })
    res.status(204).json({})
  } catch (err) {
    next(err)
  }
})

// 错误处理中间件,在此之前所有路由中调用 next(err) 都会进入这里
// 注意:必须具备 4 个参数才会被标识为错误处理中间件
app.use((err, req, res, next) => res.status(500).json({ error: err.message }))

app.listen(3000, () => console.log('Example app listening at http://localhost:3000 ......'))

代码附件下载

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 接口设计
  2. 2. 接口服务实现
  3. 3. 代码附件下载