Vue+element+Nodejs学习记录(2)

1.异步回调和Promise使用

我们先看一个异步数据读取的过程:

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

//resolve可以通过拼接多个步骤的方式把文件名拼出来,__dirname是指当前目录
const fullFileName = path.resolve(__dirname,'files','a.json')

fs.readFile(fullFileName,(err,data) => {

	if(err){
		console.error(err)
		return
	}
	//fs.readFile 读出来的data数据是二进制的流文件,所以要经过toString转换
	console.log(data.toString())

})

我们想封装这个读取文件的函数,并测试多次回调:

//数据a.json b.json c.json是一个嵌套关系
a.json 
{
    "next": "b.json",
    "msg": "this is a"
}
b.json 
{
    "next": "c.json",
    "msg": "this is b"
}
c.json
{
    "next": null,
    "msg": "this is c"
}

// callback 方式获取一个文件的内容
function getFileContent(fileName, callback) {
    const fullFileName = path.resolve(__dirname, 'files', fileName)
    fs.readFile(fullFileName, (err, data) => {
        if (err) {
            console.error(err)
            return
        }
        callback(
            JSON.parse(data.toString())
        )
    })
}

// 测试 callback-hell (aData是参数,上面的JSON.parse(data.totring是实参,aData是形参)。)
getFileContent('a.json', aData => {
    console.log('a data', aData)
    getFileContent(aData.next, bData => {
        console.log('b data', bData)
        getFileContent(bData.next, cData => {
            console.log('c data', cData)
        })
    })
})

在这里插入图片描述

Promise对于多次回调的解决方案

// 用 promise 获取文件内容
function getFileContent(fileName) {
    const promise = new Promise((resolve, reject) => {
        const fullFileName = path.resolve(__dirname, 'files', fileName)
        fs.readFile(fullFileName, (err, data) => {
            if (err) {
                reject(err)
                return
            }
            resolve(
                JSON.parse(data.toString())
            )
        })
    })
    return promise
}

getFileContent('a.json').then(aData => {
    console.log('a data', aData)
    return getFileContent(aData.next)
}).then(bData => {
    console.log('b data', bData)
    return getFileContent(bData.next)
}).then(cData => {
    console.log('c data', cData)
})

async/await同步形式解决多次回调

function getFileContent(fileName) {
    const promise = new Promise((resolve, reject) => {
        const fullFileName = path.resolve(__dirname, 'files', fileName)
        fs.readFile(fullFileName, (err, data) => {
            if (err) {
                reject(err)
                return
            }
            resolve(
                JSON.parse(data.toString())
            )
        })
    })
    return promise
}

async function readFileData() {
    // 同步写法
    try {
        const aData = await getFileContent('a.json')
        console.log('a data', aData)
        const bData = await getFileContent(aData.next)
        console.log('b data', bData)
        const cData = await getFileContent(bData.next)
        console.log('c data', cData)
    } catch (err) {
        console.error(err)
    }
}

readFileData()

// async await 要点:
// 1. await 后面可以追加 promise 对象,获取 resolve 的值
// 2. await 必须包裹在 async 函数里面
// 3. async 函数执行返回的也是一个 promise 对象
// 4. try-catch 截获 promise 中 reject 的值

Promise的实例的then方法是定义在原型对象Promise.prototype上的,then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数,then方法返回的是一个新的Promise实例,因此可以采用链式写法,如下,前一个回调函数的返回结果会作为参数传递给下一个回调函数。

//数据a.json b.json c.json是一个嵌套关系
a.json 
{
    "next": "b.json",
    "msg": "this is a"
}
b.json 
{
    "next": "c.json",
    "msg": "this is b"
}
c.json
{
    "next": null,
    "msg": "this is c"
}

getFileContent('a.json').then(aData => {
    console.log('a data', aData)
    return getFileContent(aData.next)
}).then(bData => {
    console.log('b data', bData)
    return getFileContent(bData.next)
}).then(cData => {
    console.log('c data', cData)
})

promise 的then方法默认情况下返回一个resolve状态的新的promise,而且resolve函数的参数是then里面return的值,所以最终结果是返回一个promise,resolve用 SuccessModel格式化了的值

const result = getList(author,keyword)
return result.then( listData => {
	return new SuccessModel(listData)
})

2.MySQL操作

sql增删改查: 

1、增: insert into 表名 ( 字段1,字段2 ) values ( 'a','b' ); 

2、删:delete from 表名 where 字段名 ='ab'; 

3、改: update 表名 set 字段名='ab' where ...; 

4、 查:select * from 表名; 

在这里插入图片描述

在这里插入图片描述

我们使用MySQL语句后返回的数据格式:

select * from users

//输出结果
[ 
RowDataPacket {
    id: 1,
    username: 'yangyang',
    password: '123321',
    realname: '洋洋' 
 },
RowDataPacket { 
  	id: 2, 
  	username: 'xie', 
  	password: '123321', 
  	realname: '谢' 
 }
]

更新数据显示结果:

在这里插入图片描述
插入数据显示效果:

在这里插入图片描述
这些行数和ID后面都要使用到。

3.数据库中vachar和text/longtext区别

varchar和text/longtext都可以用来存储文本格式,那么有什么区别?

1、char,存定长,速度快,存在空间浪费的可能,会处理尾部空格,上限255。
2、varchar,存变长,速度慢,不存在空间浪费,不处理尾部空格,上限65535,但是有存储长度实际65532最大可用。
3、text,存变长大数据,速度慢,不存在空间浪费,不处理尾部空格,上限65535,会用额外空间存放数据长度,顾可以全部使用65535。

总结:
经常变化的字段用varchar;
知道固定长度的用char;
尽量用varchar;
超过255字节的只能用varchar或者text;
能用varchar的地方不用text;
能够用数字类型的字段尽量选择数字类型而不用字符串类型的(电话号码),这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接回逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

参考文章:
https://www.cnblogs.com/billyxp/p/3548540.html
https://blog.csdn.net/mjshldcsd/article/details/78541323

4.利用模板文本进行SQL语句拼接

//之前的SQL拼接
var sql = "delete from users where id = " + uid;

//模板文本的SQL拼接
const getList = (author,keyword) => {

	//where 1=1 是为了保证拼接sql语句正确,因为如果没有author/keyword,整个语句也不会错。
	let sql = `select * from myblog where 1=1`

	if(author){
		sql += ` and author='${author}' `
	}
	if(keyword){
		sql += ` and title like '%${keyword}%' `
	}

	sql += ` order by createtime desc; `

	//返回promise
	return exec(sql)
	
}

5.整理下整个处理流程

conf/db.js配置好dev和production环境下,数据库配置,方便直接调用。
db/mysql.js利用上面配置好的参数,然后定义统一的sql执行函数,参数为sql,这个sql由外部传入。返回一个Promise实例。

controller中的blog.js和user.js就可以调用mysql.js中的统一定义的函数,定义getList,getDetail,newBlog,updateBlog,delBlog,loginCheck等函数,每个函数都有sql语句,调用传入的exec函数,exec(sql),返回的是Promise实例。

router中的blog.js和user.js就可以通过传入参数,调用getList,getDetail,newBlog,updateBlog,delBlog,loginCheck,返回的是SQL语句执行的结果,是Promise实例,所以可以进行.then操作,利用model中的resModel对数据进行加工,返回一个特定格式的数据。

app.js通过调用定义的路由,返回数据res.end(JSON.stringify(blogData))。app.js导出回调函数。

bin中www.js再调用app.js中的回调函数。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章