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中的回調函數。