Node学习(四)-Resful风格-BFF

一、Resful风格

【相同的地址不同请求方式,相同请求方式不同地址】

1.1基于图书馆案例改造

RESful 风格 API
GET    http://localhost:8080/books            获取图书
POST   http://localhost:8080/books/book       添加图书
GET    http://localhost:8080/books/book/:id   根据id获取图书
PUT    http://localhost:8080/books/book       编辑图书
DELETE http://localhost:8080/books/book/:id   删除图书

(一)将原本ajax中的url和type全部替换
(二)id获取问题:

ctx.request.query.editid====换为==>ctx.params.id

二、 es module

2.1 上篇

(一)新建es.html
(二)新建路由

_.get('/es',contro.actionEs()) 

(三)在controller中编写路由对应方法

actionEs(){
    return async function (ctx) {
        await ctx.render('es',{});
    }
}

(四)编写es.js

class person {
    constructor(){}

    fn(){
        console.log('===>',"es module");
    }
}
export default person;

(五)在es.html中获取js中的方法

<h2>hello</h2>
<!-- <script src="/js/es.js"></script> -->
<script>
    import('/js/es.js').then(_=>{
        console.log('_default',_.default)

        let Person = _.default;
        let person = new Person;
        person.fn();
    })
</script>

2.1 下篇

(一)安装@babel/cli、@babel/core、@babel/plugin-transform-modules-systemjs
(二)“build”: “babel ./assets/js/es.js -o ./assets/js/es_bundle.js”
(三)创建.babelrc文件

{
    "plugins": ["@babel/plugin-transform-modules-systemjs"]
}

(四)es.html中

<h2>hello</h2>
    <script nomodule src="https://cdn.staticfile.org/systemjs/6.8.3/system.min.js"></script>
    <!-- <script src="/js/es.js"></script> -->
    <script type="module">
        console.log("====>",'支持 es module')
        import('/js/es.js').then(_=>{
            console.log('_default',_.default)

            let Person = _.default;
            let person = new Person;
            person.fn();
        })
    </script>
     <script nomodule>
        System.import('/js/es_bundle.js').then(_=>{
            console.log('_default====>','system module')

            let Person = _.default;
            let person = new Person;
            person.fn();
        })
    </script>

三、 服务器端发起请求

在这里插入图片描述

3.1请求别人的网站

const http = require('http');
const fs = require('fs');
const path = require('path');

let req = http.request('http:/www.taobao.com',res=>{
    let result = '';
    res.on('data',chunk=>{
        result += chunk;
    })
    res.on('end',() => {
        // console.log('=====>','数据接收完成');
        // console.log('result ====>',result);
        fs.writeFile(path.join(__dirname,'baidu.html'), result, err => {
            if(err) {
                console.log(' ====>','err');
                return;
            }
            console.log(' ====>','success')
        })
    })

});
req.end();

3.2 请求自己的

const http = require('http');

let req = http.request('http://localhost:8080/books',res=>{
    let result = '';
    res.on('data',chunk=>{
        result += chunk;
    })
    res.on('end',() => {
        console.log('result ====>',result);
    })
});
req.end();

(一)第一步 运行图书管理系统服务器
(二)第二步 在运行这个服务器

3.3 请求后–>加数据

const http = require('http');
const querystring = require('querystring');
let obj={
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
    }
}
//http://nodejs.cn/api/http.html#http_http_request_url_options_callback
let req = http.request('http://localhost:8080/books/book',obj, res=>{
    let result = '';
    res.on('data',chunk=>{
        result += chunk;
    })
    res.on('end',() => {
        console.log('result ====>',result);
    })
});
//querystring查询字符串 不光是模块 也是术语
const postData = querystring.stringify({
    'name': '你好世界',
    'author': '你好世界',
    'category': '你好世界',
    'description': '你好世界'
});
//打印瞅瞅是啥东东
console.log('postData===>',postData)
// 将数据写入请求主体。
req.write(postData);
req.end();

3.4 请求后–>修改数据

在这里插入图片描述

3.5 请求后–>删除数据

const http = require('http');
let obj={
    method: 'delete',
}
//http://nodejs.cn/api/http.html#http_http_request_url_options_callback
let req = http.request('http://localhost:8080/books/book/22',obj, res=>{
    let result = '';
    res.on('data',chunk=>{
        result += chunk;
    })
    res.on('end',() => {
        console.log('result ====>',result);
    })
});
req.end();

四、 BFF

4.1概念

Backend For Frontend (服务于前端的后端)

专门用于为前端业务提供数据的后端程序,这类程序的特点是不需要太强的服务器运算能力,但对程序的灵活性有较高的要求,这两个特点都正好和 nodejs 的优势相吻合,在 web 服务开发领域搭建一个 nodejs BFF 层是有很大的好处的。

对于 web 业务本身来说,nodejs 现在是最合适用来做 BFF 层的一门技术。有一个 nodejs BFF 层,能让前端有能力自由组装后台数据,这样可以减少大量的业务沟通成本,加快业务的迭代速度。同时前端工程师能自主决定前端与后台的通信方式,也让前端工程师有了更多的能力着手于 web 应用的性能优化。
在这里插入图片描述

4.2 本案例基于图书馆案例

首先在概念图的基础上进行
在这里插入图片描述

4.2.1左边的路由index.js
const router = require('koa-simple-router')
//返回页面的
const controllers = require('./indexController');
const contro = new controllers();
//返回接口
const APIContributors = require('./APIController')
const apicontro = new APIContributors();

let controller = (app) => {
    //返回页面
    app.use(router(_ => {
        //返回主页
        _.get('/',contro.index())
        _.get('/index',contro.index())
        _.get('/es',contro.actionEs())          
    }))
    //返回接口
    app.use(router({ prefix: '/api' }, _ => {
        //测试用
        // _.get('/test',ctx =>{
        //     ctx.body = "hahahah"
        // })
        //获取图书
        _.get('/books',apicontro.adminindex())
        //添加图书页
        // _.get('/books/book',contro.actionAddPage())
        _.post('/books/book',apicontro.actionAdd())    
    }))
}
module.exports = controller;
4.2.2controller下的APIController.js
let IndexBookModel = require('../models');
let indexBookModel = new IndexBookModel(); 

class APIContributors{
    constructor(){} 
    //获取图书
    adminindex(){
        return async function (ctx) {
            let msg = await indexBookModel.getData();
            //要前端渲染  将msg传给页面
            ctx.body = msg;
        }
    }
    //添加图书
    actionAdd(){
        return async function (ctx) {  
            // console.log(ctx.request.body)        
            try{
                let msg = await indexBookModel.addData(ctx.request.body);
                // console.log('msg',msg)
                if(msg.code == 0){
                    // console.log(1)
                    //返回数据
                    ctx.body = msg;
                }else{
                    ctx.body = '添加失败!'
                }               
            }catch(err){
                console.log('err',err)
            }            
        }
    }
}
module.exports = APIContributors;
4.2.3models下的index.js
const SafeRequest = require('../util/SafeRequest');
class IndexBookModel{
    constructor(){}
    //获取数据
    getData(){
        let safeRequest = new SafeRequest('/books');
        return safeRequest.fetch();
    }
    //处理图书
    addData(opt){
        let safeRequest = new SafeRequest('/books/book');
        
        return safeRequest.fetch({
            method: 'post',
            params: opt
        });
    }
}
module.exports = IndexBookModel;
4.2.4util下的SafeRequest
const config = require('../config')
const axios = require('axios');
class SafeRequest{
    constructor(url){
        this.baseUrl = config.baseURL,
        this.url = url;
    }
    fetch(options){
        // console.log(this.baseUrl + this.url)
        let bookFetch = axios.get(this.baseUrl + this.url);
        if(options){
            console.log(options.params)
            bookFetch = axios({
                url: this.baseUrl + this.url,
                method: options.method,
                data: options.params
            })
        }

        return new Promise((resolve, reject) =>{
            let result = {
                code:0,
                message:'',
                data:[]
            }
            bookFetch
                .then(msg =>{
                    // console.log('msg====>',msg);
                    if(msg.data.code && msg.data.code == 0){
                        result.data = msg.data.data;
                        result.message = msg.data.message;
                    }else{
                        result.data = msg.data;
                    }
                    result.data = msg.data;
                    resolve(result);
                })
                .catch(err =>{
                    result.code = 1;
                    result.message = '与后台通信失败';
                    reject(result);
                })
        })  
    }
}
module.exports = SafeRequest;
4.2.4config下的index.js
const _ = require('lodash')
const path = require('path')

let config = {
    "staticDir": path.join(__dirname, '..', 'assets'),
    "templateDir": path.join(__dirname, '..', 'views')
}
if(process.env.NODE_ENV == 'development'){
    let localPort = {
        port: 8080,
        baseURL:`http://localhost:8088`
    };
    _.assignIn(config, localPort)
}
if(process.env.NODE_ENV == 'production'){
    let prodPort = {
        port: 80
    };
    _.assignIn(config, prodPort)
}
module.exports = config;

使用Postman进行测试添加模块
在这里插入图片描述

axios的功能特点:
(一)在浏览器中发生XMLHttprequest请求;(二)在node.js中发生http请求;(三)基于promise API;(四)拦截请求和响应;(五)转换请求数据和响应数据;(六)自动转换JSON数据;(七)客户端支持防御XSRF;

Node学习(一)
Node学习(二)
Node学习(三)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java亮小白1997

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值