Node本地起一个服务器

1,991 阅读3分钟

这里简单的介绍下xmall商城实战项目中,通过express(创建app实例)、body-parse(解决跨域问题)、cors(解决跨域问题)、jsonwebtoken(用于token验证;当然这里面提到的都是需要安装的哈,目录结构如下:

xmallserve              
├─ db                //database数据          
│  ├─ allGoods.json     
│  ├─ cartList.json     
│  ├─ goodsDetail.json  
│  └─ home.json         
├─ app.js               
├─ package-lock.json    
└─ package.json         

1.创建

  1. 首先创建一个xmallserve文件夹,然后新建一个app.js文件;
  2. 在项目目录下执行npm init --yes 初始化
  3. npm install express body-parse cors jsonwebtoken -S 依赖

2.app.js

const express = require('express');
const app = express();//创建app实例
const fs = require('fs');

/**
 *
 * @param {*当前页的数量} pageSize
 * @param {*当前页} currentPage
 * @param {*当前数组} arr
 *
 * 总32条
 * 8
 * 1 2
 */
function pagination(pageSize, currentPage, arr) {
    let skipNum = (currentPage - 1) * pageSize;
    let newArr = (skipNum + pageSize >= arr.length) ? arr.slice(skipNum, arr.length) : arr.slice(skipNum, skipNum + pageSize);
    return newArr;
}

// 升序还是降序
/**
 *
 * @param {*排序的属性} attr
 * @param {*true表示升序排序 false表示降序排序} rev
 */

function sortBy(attr, rev) {
    if (rev === undefined) {
        rev = 1;
    } else {
        rev = rev ? 1 : -1;
    }
    return function (a, b) {
        a = a[attr];
        b = b[attr];
        if (a < b) {
            return rev * -1;
        }
        if (a > b) {
            return rev * 1;
        }
        return 0;
    }
}
function range(arr, gt, lte) {
    return arr.filter(item => item.salePrice >= gt && item.salePrice <= lte)
}
const cors = require('cors');
const jwt = require('jsonwebtoken')
const bodyParser = require('body-parser');
const cartListJSON = require('./db/cartList.json');
//下面3行代码是解决跨域问题的
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }))
app.get('/api/goods/home', (req, res) => {
    fs.readFile('./db/home.json', 'utf8', (err, data) => {
        if (!err) {
            res.json(JSON.parse(data));
        }
    })
})
app.get('/api/goods/allGoods', (req, res) => {
    // 获取的是前端地址栏上的查询参数
    const page = parseInt(req.query.page) || 1;
    const size = parseInt(req.query.size) || 20;
    const sort = parseInt(req.query.sort) || 1;
    const gt = parseInt(req.query.priceGt);
    const lte = parseInt(req.query.priceLte);
    const cid = req.query.cid;
    let newData = []
    fs.readFile('./db/allGoods.json', 'utf8', (err, data) => {
        let { result } = JSON.parse(data);
        let allData = result.data;
        // 分页显示
        newData = pagination(size, page, allData);
        if (cid === '1184') { //品牌周边
            newData = allData.filter((item) => item.productName.match(RegExp(/Smartisan/)))
            if (sort === 1) { //价格由低到高
                newData = newData.sort(sortBy('salePrice', true))
            } else if (sort === -1) { //价格由高到低
                newData = newData.sort(sortBy('salePrice', false))
            }
        } else {
            if (sort === 1) { //价格由低到高
                newData = newData.sort(sortBy('salePrice', true))
            } else if (sort === -1) { //价格由高到低
                newData = newData.sort(sortBy('salePrice', false))
            }
            if (gt && lte) {
                // 过滤 10~1000
                newData = range(newData, gt, lte)
            }
            // 32
        }
        if (newData.length < size) {
            res.json({
                data: newData,
                total: newData.length
            })
        } else {
            res.json({
                data: newData,
                total: allData.length
            })
        }
    })
})
// 商品详情的数据
app.get('/api/goods/productDet', (req, res) => {
    const productId = req.query.productId;
    console.log(productId);
  //读取goodsDetail.json文件中的内容
    fs.readFile('./db/goodsDetail.json', 'utf8', (err, data) => {
        if (!err) {
            let { result } = JSON.parse(data);
            let newData = result.find(item => item.productId == productId)
            res.json(newData)
        }
    })
})

// 模拟一个登陆的接口
app.post('/api/login', (req, res) => {
    // 登录成功获取用户名(通过req.body....方式获取字段内容)
    let username = req.body.user
    let password = req.body.pass
    //一系列的操作
    res.json({
        // 进行加密的方法
        // sign 参数一:加密的对象 参数二:加密的规则 参数三:对象
        token: jwt.sign({ username,password }, 'abcd', {
            // 过期时间
            expiresIn: "3000s"
        }),
        username,
        state: 1,
        file: '/static/images/1570600179870.png',
        code: 200,
        address: null,
        balance: null,
        description: null,
        email: null,
        message: null,
        phone: null,
        points: null,
        sex: null,
        id: 62
    })
})

// 登录持久化验证接口 访问这个接口的时候 要访问token(前端页面每切换一次,就访问一下这个接口,问一下我有没有登录/登陆过期)
// 先访问登录接口,得到token,在访问这个,看是否成功
app.post('/api/validate', function (req, res) {
    let token = req.headers.authorization;
    console.log(token);
    // 验证token合法性 对token进行解码
    jwt.verify(token, 'abcd', function (err, decode) {
        if (err) {
            res.json({
                msg: '当前用户未登录'
            })
        } else {
            // 证明用户已经登录
            res.json({
                token: jwt.sign({ username: decode.username }, 'abcd', {
                    // 过期时间
                    expiresIn: "3000s"
                }),
                username: decode.username,
                msg: '已登录',
                address: null,
                balance: null,
                description: null,
                email: null,
                file: "/static/images/1570600179870.png",
                id: 62,
                message: null,
                phone: null,
                points: null,
                sex: null,
                state: 1,
            })
        }
    })
})


app.post('/api/addCart', (req, res) => {
    let { userId, productId, productNum } = req.body;
    fs.readFile('./db/allGoods.json', (err, data) => {
        let { result } = JSON.parse(data);
        if (productId && userId) {
            let { cartList } = cartListJSON.result.find(item => item.id == userId)
            // 找到对应的商品
            let newData = result.data.find(item => item.productId == productId);
            newData.limitNum = 100;

            let falg = true;
            if (cartList && cartList.length) {
                cartList.forEach(item => {
                    if (item.productId == productId) {
                        if (item.productNum >= 1) {
                            falg = false;
                            item.productNum += parseInt(productNum);
                        }
                    }
                })
            }
            if (!cartList.length || falg) {  //购物车为空
                newData.productNum = parseInt(productNum)
                cartList.push(newData);
            }

            // 序列化

            fs.writeFile('./db/cartList.json', JSON.stringify(cartListJSON), (err) => {
                if (!err) {
                    res.json({
                        code: 200,
                        message: "success",
                        result: 1,
                        success: true,
                        timestamp: 1571296313981,
                    })
                }
            })
        }

    })

})

app.post('/api/cartList', (req, res) => {
    let { userId } = req.body;
    fs.readFile('./db/cartList.json', (err, data) => {
        let { result } = JSON.parse(data);
        let newData = result.find(item => item.id == userId);
        res.json({
            code: 200,
            cartList: newData,
            success: true,
            message: 'success'
        })
    })
})

//监听了3000端口
app.listen(3000,()=>{
    console.log('服务器启动在3000端口上');
});

到这里,正常是通过node app.js去启动服务的,但是通过node直接去启动服务,一旦文件改变就需要重复的去执行node app.js命令;

这里推荐使用nodemon app.js(自己全局安装),这样的话,如果项目内文件发生变化,会进行热更,不需要再执行node app.js重启服务。

服务器启动后 ,通过http://localhost:3000/api/goods/home(这里只是用api/goods/home来举个例子,其他接口也可以),就可以通过http://localhost:3000/api/goods/home在浏览器访问到数据了,你学废了嘛,哈哈哈哈哈....