express寫CRUD需求接口案例

需求:實現(xiàn)對任務(wù)清單的CRUD接口服務(wù)

  • 查詢?nèi)蝿?wù)列表
    GET /todos

  • 根據(jù) ID 查詢單個任務(wù)
    GET /todos/:id

  • 添加任務(wù)
    POST /todos

  • 修改任務(wù)
    PATCH /todos/:id

  • 刪除任務(wù)

DELETE /todos/:id

目錄結(jié)構(gòu)及啟動示意圖

代碼視圖

  • app.js項目入口文件
const express = require('express')
const fs = require('fs')
const { getDb, saveDb } = require('./db')
const app = express()
const bodyParser = require('body-parser') 
app.use(express.json()) //配置解析表單請求頭:application/json
app.use(express.urlencoded()) //配置解析表單請求頭:application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

app.get('/todos', async (req, res) => {
    try {
        const db = await getDb()
        res.status(200).json(db.todos)
    } catch (err) {
        res.status(500).json({
            error: err.message
        })
    }
})

app.get('/todos/:id', async (req, res) => {
    try {
        const db = await getDb()
        const todo = db.todos.find(todo => todo.id === Number.parseInt(req.params.id))
        if (!todo) {
            return res.status(404).end()
        }
        res.status(200).json(todo)
    } catch (err) {
        res.status(500).json({
            error: err.message
        })
    }
})

/** 2.增加接口**/
app.post('/todos', async (req, res) => {
    try {
        const todo = req.body // 1.獲取客戶端請求參數(shù)
        console.log(todo.title);
        if (!todo.title) { // 2.數(shù)據(jù)驗證
            return res.status(422).json({
                error: 'The field title is required.'
            })
        }
        // 3.數(shù)據(jù)驗證通過潦闲,把數(shù)據(jù)存儲到db中
        const db = await getDb()
        const lastTodo = db.todos[db.todos.length - 1]
        //id唯一蚯嫌,重新寫入到db文件中不覆蓋,db文件是空的話贰盗,id = 1
        todo.id = lastTodo ? lastTodo.id + 1 : 1,
        db.todos.push(todo)
        await saveDb(db) //保存文件
        // 4.發(fā)送響應(yīng)
        res.status(201).json(todo)
    } catch (err)  {
        res.status(500).json({
            error: err.message
        })
    }
})

/* 3.修改接口 */
app.patch('/todos/:id', async (req, res) => {
    try {
      const todo = req.body //獲取表單數(shù)據(jù)
      //查找到要修改的任務(wù)項
      const db = await getDb()
      const result = db.todos.find(todo => todo.id === Number.parseInt(req.params.id))
      if(!result){ //修改項不存在
          return res.status(404).end()
      }
      Object.assign(result,todo) //合并數(shù)據(jù)
      await saveDb(db) //數(shù)據(jù)存儲
      res.status(200).json(result)
    } catch (err) {
        res.status(500).json({
            error: err.message
        })
    }
})

/* 4.刪除接口 */
app.delete('/todos/:id', async (req, res) => {
    try {
        //查找到要修改的任務(wù)項
        const todoId = Number.parseInt(req.params.id)
        const db = await getDb() //獲取數(shù)據(jù)庫
        const index = db.todos.findIndex(todo => todo.id === todoId) //根據(jù)索引進行刪除
        if(index === -1){ // -1代表找不到
            return res.status(404).end
        }
        db.todos.splice(index,1) //根據(jù)索引刪除一項
        await saveDb(db) //數(shù)據(jù)存儲
        res.status(204).end() //發(fā)送狀態(tài)碼并且結(jié)束響應(yīng)
      } catch (err) {
          res.status(500).json({
              error: err.message
          })
      }
})

app.listen(3000, () => {
    console.log('Server is running at http://localhost:3000');
})


/*
    沒封裝db.js的寫法
*/
// app.get('/todos', (req, res) => {
//     fs.readFile('./db.json', 'utf-8', (err, data) => {
//         if (err) {
//             res.status(500).json({
//                 error: err.message
//             })
//         }
//         const db = JSON.parse(data)
//         res.status(200).json(db.todos)
//     })
// })
  • db.js 是一個封裝好的db模塊航揉,封裝了用于讀取和保存數(shù)據(jù)的方法唆阿。
/*
    封裝db模塊
*/

const fs = require('fs')
const { promisify } = require('util')
const readFile = promisify(fs.readFile) //提供promise支持的異步讀文件操作
const writeFile = promisify(fs.writeFile)
const path = require('path')

const dbPath = path.join(__dirname,'./db.json') //動態(tài)拼接路徑 
exports.getDb = async () => {
    const data = await readFile(dbPath, 'utf-8')
    return JSON.parse(data) //讀取json文件并轉(zhuǎn)換
}

exports.saveDb = async db => {
    const data = JSON.stringify(db, null, '  ') //后2個參數(shù)讓寫入內(nèi)容的時候是換行對其
    await writeFile(dbPath, data)
}
  • db.json 模擬充當數(shù)據(jù)庫存儲
{
  "todos": [
    {
      "id": 1,
      "title": "看電視"
    },
    {
      "id": 2,
      "title": "吃飯"
    },
    {
      "id": 3,
      "title": "敲代碼"
    },
    {
      "title": "看電視",
      "id": 4
    }
  ],
  "users": []
}

Postman工具測試檢驗接口

  1. 查詢?nèi)蝿?wù)列表


  2. 根據(jù)ID查詢單個任務(wù)


  3. 添加任務(wù)項



    我們再來看看db.json有沒有多出了id為5的任務(wù)項刁卜。


  4. 根據(jù)ID修改查詢到的單個任務(wù)



    db.json有沒有修改成功蠢正?


  5. 根據(jù)ID刪除查詢到的單個任務(wù)



    db.json查看還有沒有id為4的任務(wù)項闯割。


express.json()和express.urlencoded()的區(qū)別

以POSTMAN工具為例子

  • 總結(jié):express.urlencoded()以鍵值對的形式填寫請求彻消,express.json()以json格式填寫請求.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市宙拉,隨后出現(xiàn)的幾起案子证膨,更是在濱河造成了極大的恐慌,老刑警劉巖鼓黔,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件央勒,死亡現(xiàn)場離奇詭異,居然都是意外死亡澳化,警方通過查閱死者的電腦和手機崔步,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缎谷,“玉大人井濒,你說我怎么就攤上這事×辛郑” “怎么了瑞你?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長希痴。 經(jīng)常有香客問我者甲,道長,這世上最難降的妖魔是什么砌创? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任虏缸,我火速辦了婚禮鲫懒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刽辙。我一直安慰自己窥岩,他們只是感情好,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布宰缤。 她就那樣靜靜地躺著颂翼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慨灭。 梳的紋絲不亂的頭發(fā)上疚鲤,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天,我揣著相機與錄音缘挑,去河邊找鬼集歇。 笑死,一個胖子當著我的面吹牛语淘,可吹牛的內(nèi)容都是我干的诲宇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惶翻,長吁一口氣:“原來是場噩夢啊……” “哼姑蓝!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吕粗,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤纺荧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后颅筋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宙暇,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年议泵,在試婚紗的時候發(fā)現(xiàn)自己被綠了占贫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡先口,死狀恐怖型奥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情碉京,我是刑警寧澤厢汹,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站谐宙,受9級特大地震影響烫葬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜卧惜,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一厘灼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咽瓷,春花似錦设凹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至钻洒,卻和暖如春奋姿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背素标。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工称诗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人头遭。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓寓免,卻偏偏與公主長得像,于是被迫代替她去往敵國和親计维。 傳聞我的和親對象是個殘疾皇子袜香,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353