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

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