Node零基礎(chǔ)入門到服務端程序 -- 第四章

第四章 入?yún)⒑万炞C入?yún)?/h2>

之前我們寫了一個接口,把所有的書本數(shù)據(jù)都提供給了api,現(xiàn)在我們再寫一個接口,通過豐富之前的代碼,用于搜索書本。

搜索功能,我們知道,大約是在輸入框中填入某些內(nèi)容,然后接口返回與內(nèi)容相關(guān)的數(shù)據(jù),那么這里就涉及到一個內(nèi)容,就是通過api請求傳入服務端的內(nèi)容,我們稱之為入?yún)?。入?yún)⒃谶M入服務端之前,我們需要驗證它們的格式是否符合我們設定的要求,不符合我們要求的入?yún)⒁?guī)則的請求我們就可以直接返回報錯,不需要處理它們了。

那么驗證入?yún)⑹欠窈细裎覀兙托枰玫揭粋€新的包:Joi

npm install joi --save

tips: Joi 文檔

src/router.js

const Router = require('koa-router');
const router = new Router();
// 這是一個用于驗證入?yún)⑹欠裾_的包
const Joi = require('joi');
// 創(chuàng)建一個函數(shù)用于驗證入?yún)⑹欠裾_
const { validatorInterceptor } = require('./lib');
const { BookController } = require('./controllers/book-controller');
router.get('/', ctx => ctx.body = 'Web API Running Successfully.');
router.get('/api/books', BookController.get);
// 用于驗證入?yún)?const bookSearchSchema = {
    query: Joi.object().keys({
        // 這里要求入?yún)⒖梢杂忻麨閟earch_text的參數(shù),且必須是字符串
        text: Joi.string(),
    }),
};
// 第一個參數(shù)依舊是路由地址,第二個參數(shù)我們驗證入?yún)⑹欠窈细竦暮瘮?shù)放在這里,第三個參數(shù)是controller執(zhí)行層
router.get('/api/book/search', validatorInterceptor(bookSearchSchema), BookController.get);
module.exports = router;

上面我們創(chuàng)建了一個用于驗證入?yún)⑹欠窈细竦暮瘮?shù),由于這個函數(shù)為公用方法,那么我們創(chuàng)建一個lib文件夾,并把它寫在index.js里面

src/index.js

// 這是一個在node中非常常用且好用的包,用于處理各種數(shù)據(jù)(如json,數(shù)組等)重組,使用npm install lodash安裝
const _ = require('lodash');
// 這個函數(shù)同樣要使用到Joi,所以依然引入它
const Joi = require('joi');
exports.validatorInterceptor = async (schemas, options) => {
    // 這里我們給validatorInterceptor返回一個函數(shù)
    return async (ctx, next) => {
        try {
            // 將傳入的schemas的key全部取出,并循環(huán)它們
            for (const key of _.keys(schemas)) {
                // 使用validate方法驗證每一個key是否符合要求
                await Joi.validate(_.get(ctx.request, key), _.get(schemas, key), options || {});
            }
        }
        // 如果不符合要求,則直接報400錯誤
        catch (err) {
            ctx.throw(400, `validation failed on: ${err.message}`);
        }
        // 如果沒有問題,則下一步
        await next();
    };
}

tips: lodash 文檔

剛才可以發(fā)現(xiàn),搜索api我們使用的還是get方法,那么現(xiàn)在我們就來改裝一下這個方法

src/controllers/book-controller.js

const { BookService } = require('../services/book-service');
class BookController {
    static async get(ctx) {
        // 我們將入?yún)腸tx.request.query中取出
        const searchText = ctx.request.query.text;
        const bookService = new BookService();
        // 傳入service方法中使用
        const res = await bookService.get(searchText);
        ctx.body = res;
    }
}
module.exports = { BookController };

接著修改service方法

src/services/book-services.js

const bookModel = require('../schemas/book-schema');
class BookService {
    // 這個函數(shù)的入?yún)閯偛與ontroller層傳入的搜索內(nèi)容
    async get(searchText) {
        // 我們設置一個默認的內(nèi)容,就是當接口什么搜索內(nèi)容都沒有傳入的時候,我們默認返回所有書本給接口
        const query = {};
        // 當有搜索內(nèi)容傳入的時候
        if (searchText) {
            // 我們希望數(shù)據(jù)庫無論是書本名稱還是作者,有相關(guān)的文字內(nèi)容就可以將其搜索出來
            // 這里的$or和后面的內(nèi)容寫法都是mongo搜索時的寫法,有不了解的同學可以查看mongo相關(guān)文檔學習
            query.$or = [{name: new RegExp(searchText)}, {author: new RegExp(searchText)}];
        }
        // 和之前一樣,查詢數(shù)據(jù),然后將結(jié)果返回
        const res = await bookModel.find(query);
        return res;
    }
}
module.exports = { BookService };

接下來,啟動程序,開始驗證我們的代碼編寫成果

node src/server.js

打開瀏覽器

首先無任何參數(shù),我們希望返回所有的書本數(shù)據(jù):http://localhost:3000/api/book/search

圖片

當參數(shù)錯誤時:http://localhost:3000/api/book/search?aaa=111

圖片

搜索書本名稱,三體:http://localhost:3000/api/book/search?text=三體

圖片

搜索作者名稱,村上春樹:http://localhost:3000/api/book/search?text=村上春樹

圖片

搜索不完全的書本名稱,挪威:http://localhost:3000/api/book/search?text=挪威

圖片

全部成功,我們的搜索接口,就是這么簡單 __

本文已完成電子書《Node零基礎(chǔ)入門到服務端程序》電子書(含教程內(nèi)項目代碼)/ 10元,購買鏈接:https://mianbaoduo.com/o/bread/mbd-Z5WZk5o=
ps:前九章(本書共計十三章)內(nèi)容會在這里陸續(xù)更新。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容