koa2框架筆記
Node.js是一一個異步的世界,官方API支持的都是callback 形式的異步編程模型剔宪,這會帶來許多問題例如:
- callback 嵌套問題
- 異步函數(shù)中可能同步調(diào)用callback返回數(shù)據(jù)佑颇,帶來不一致性馋劈。
為了解決以上問題Koa出現(xiàn)了
Koa--基于Node.js 平臺的下一代web開發(fā)框架
koa是由Express 原班人馬打造的维蒙,致力于成為一個更小简烤、更富有表現(xiàn)力错蝴、更健壯的Web框架洲愤。使用 koa編寫web應用,可以免除重復繁瑣的回調(diào)函數(shù)嵌套顷锰,并極大地提升錯誤處理的效率柬赐。koa不在內(nèi)核方法中綁定任何中間件,它 僅僅提供了一個輕量優(yōu)雅的函數(shù)庫官紫,使得編寫Web應用變得得心應手肛宋。開發(fā)思路和express差不多,最大的特點就是可以避免異步嵌套束世。
koa2利用ES7的async/await特性酝陈,極大的解決了我們在做nodejs開發(fā)的時候異步給我們帶來的煩惱。
koa學習網(wǎng)站
- 英語官網(wǎng) http://koajs.com
- 中文官網(wǎng) http://www.itying.com/koa
Koa2.x框架的安裝使用
-
安裝Node.js 8.x以上的版本
開發(fā)Koa2之前毁涉,Node.js 是確要求的沉帮,它要求Node.js版本高于V7.6。因為node.js 7.6版本開始完全支持async/await薪丁,所以才能完全你支持Koa2遇西。
-
安裝Koa:
安裝Koa框架和我們以前安裝其他模塊是一-樣的。
npm install koa --save
-save參數(shù)严嗜,表示自動修改package.json文件粱檀,自動添加依賴項。
安裝koa2
// 初始化package.json
npm init --yes
// 安裝koa2
npm install koa
hello world代碼
//引入Koa
const koa=require(' koa ');
const app=new koa();
//配置中間件 (可以先當做路由)
app.use( async (ctx)=>{
ctx.body= 'hello koa2'
//監(jiān)聽端口
app. listen(3000);
Koa異步處理Async漫玄、Await 和Promise的使用(重點)
async是“異步”的簡寫茄蚯,而await 可以認為是async wait的簡寫压彭。所以應該很好理解async用于申明一個function 是異步的,而await 用于等待一個異步方法執(zhí)行完成渗常。
簡單理解:
- async是讓方法變成異步壮不。
- await是等待異步方法執(zhí)行完成。
詳細說明:
async function testAsync(){
return 'Hello async';
}
const result = testAsync();
console.log(result);
//輸出結(jié)果
Promise { 'Hello async' }
async是讓方法變成異步皱碘,在終端里用node執(zhí)行這段代碼询一,你會發(fā)現(xiàn)輸出了Promise {‘Helloasync’},這時候會發(fā)現(xiàn)它返回的是Promise。
await在等待async方法執(zhí)行完畢執(zhí)行
其實await等待的只是一個表達式癌椿,這個表達式在官方文檔里說的是Promise對象健蕊,但是它也可以接受普通值。注意: await 必須在async方法中才可以使用因為await訪問本身就會造成程序停止堵塞踢俄,所以必須在異步方法中才可以使用缩功。
async/await同時使用
async 會將其后的函數(shù)(函數(shù)表達式或 Lambda)的返回值封裝成一個 Promise 對象,而 await 會等待這個 Promise 完成都办,并將其 resolve 的結(jié)果返回出來嫡锌。
await阻塞的功能 把異步改成一個同步
asyne function getData() {
console.1og(2):
return '這是一個數(shù)據(jù)’;
}
async function test(){
console. log(1);
var d=await getData();
console. 1og(d);
console.1og(3);
}
test();
同步 異步 1/d/3/2
//1
//2
//這是一個數(shù)據(jù)
//3
async/await語法特點:
- 可以讓異步邏輯用同步寫法實現(xiàn)
- 最底層的await返回需要是Promise對象
- 可以通過多層async function的同步寫法來代替?zhèn)鹘y(tǒng)的callback嵌套
koa路由、get 傳值琳钉、動態(tài)路由
koa路由
路由(Routing)是由一個URI (或者叫路徑)和一一個特定的HTTP方法(GET势木、POST等)組成的,涉及到應用如何響應客戶端對某個網(wǎng)站節(jié)點的訪問槽卫。通俗的講: 路由就是根據(jù)不同的URL地址跟压,加載不同的頁面實現(xiàn)不同的功能胰蝠。
Koa中的路由和Express有所不同歼培,在Express中直接引入Express就可以配置路由,但是在Koa中我們需要安裝對應的koa-router路由模塊來實現(xiàn)茸塞。
npm install koa-router --save
const Koa = require('koa');
const Router = require('koa-router');
//實例化
const app = new Koa();
const router=new Router();
//配置路由
//ctx 上下文 context req,res等信息都放在ctx里面
router.get('/', async (ctx)=> {
ctx.body="首頁";//返回數(shù)據(jù) 原生里面的res.send()
})
router.get('/news, async(ctx)=>{
ctx.body= "這是一個新聞頁面”
});
//啟動路由
app.use(router.routes());
//可以配置也可以不配置 建議配置
app.use(router.allowedMethods());
//這是官方文檔的推薦用法躲庄,我們可以看到router.allowedMethods()用在了路由匹配router.routes()之后,所以在當所有路由中間件最后調(diào)用钾虐。 此時根據(jù)ctx.status設置response響應頭
app.listen(3000,()=>{
console.1og('starting at port 3000' ) ;
});
koa路由get傳值
在koa2中GET傳值通過request接收噪窘,但是接收的方法有兩種:query和querystring
- query:返回的是格式化好的參數(shù)對象
- querystring:返回的是請求字符串
router.get( '/news', (ctx)=>{
let url=ctx.url;
//從request中獲取GET請求
let request =ctx.request;
let req_query=request.query;
let req_querystring=request.querystring;
//從ctx中直接獲取
let ctx_query = ctx.query; //{id:123,name:123} 獲取的對象 推薦
let ctx_querystring = ctx.querystring;//id=123&name=123 獲取的字符串
ctx.body={
url,
req_ query,
req_ querystring,
ctx_ query,
ctx_ querystring
}
});
POST請求參數(shù)獲取原理
對于POST請求的處理,koa2沒有封裝獲取參數(shù)的方法效扫,需要通過解析上下文context中的原生node.js請求對象req倔监,將POST表單數(shù)據(jù)解析成query string(例如:a=1&b=2&c=3),再將query string 解析成JSON格式(例如:{"a":"1", "b":"2", "c":"3"})
注意:
ctx.request是context經(jīng)過封裝的請求對象菌仁,ctx.req是context提供的node.js原生HTTP請求對象浩习,同理ctx.response是context經(jīng)過封裝的響應對象,ctx.res是context提供的node.js原生HTTP請求對象济丘。
獲取Post請求的步驟:
- 解析上下文ctx中的原生nodex.js對象req谱秽。
- 將POST表單數(shù)據(jù)解析成query string-字符串. (例如:user=jspang&age=18)
- 將字符串轉(zhuǎn)換成JSON格式洽蛀。
// 解析上下文里node原生請求的POST參數(shù)
function parsePostData( ctx ) {
return new Promise((resolve, reject) => {
try {
let postdata = "";
ctx.req.addListener('data', (data) => {
postdata += data
})
ctx.req.addListener("end",function(){
let parseData = parseQueryStr( postdata )
resolve( parseData )
})
} catch ( err ) {
reject(err)
}
})
}
// 將POST請求參數(shù)字符串解析成JSON
function parseQueryStr( queryStr ) {
let queryData = {}
let queryStrList = queryStr.split('&')
console.log( queryStrList )
for ( let [ index, queryStr ] of queryStrList.entries() ) {
let itemList = queryStr.split('=')
queryData[ itemList[0] ] = decodeURIComponent(itemList[1])
}
return queryData
}
動態(tài)路由
router.get('/news/:id', async(ctx)=>{
//獲取動態(tài)路由的傳值
console.log(ctx.params)//{id:xxx}
ctx.body= "這是一個新聞頁面”
});
中間件
通俗的講: 中間件就是匹配路由之前或者匹配路由完成做的一系列的操作,我們就可以把它叫做中間件
在express中間件(Middleware) 是一個函數(shù)它可以訪問請求對象(request object (req)),響應對象(response object(res))和web應用中處理請求-響應循環(huán)流程中的中間件,一般被命名為next的變量疟赊。在Koa中中間件和express有點類似
中間件的功能包括:
- 執(zhí)行任何代碼
- 修改請求和響應對象
- 終結(jié)請求-響應循環(huán)
- 調(diào)用堆棧中的下一一個中間件
如果get,post回調(diào)函數(shù)中,沒有next參數(shù),那么就匹配上第一個路由,就不會往下匹配了郊供。如果想往下匹配的話,那么需要寫next()
Koa應用可使用如下幾種中間件:
- 應用級中間件
- 路由級中間件
- 錯誤處理中間件
- 第三方中間件
應用級中間件 匹配任何路由
app.use(async (ctx,next)=>{
//匹配路由之前打印日期
console.log(new Date());
await next(); //當前路由匹配完成以后繼續(xù)向下匹配
})
路由級中間件
//匹配到news路由以后繼續(xù)向下匹配路由
router.get('/news', async(ctx, next)=>{
console.log(1)
await next()
})
router.get('/news', function (ctx) {
ctx.body="Hello koa";
})
錯誤處理中間件
app.use(async (ctx,next)=> {
await next();
//如果頁面找不到
if(ctx.status==404){
ctx.status = 404;
ctx.body="這是一個404頁面"
}
});
Koa中間件的執(zhí)行順序
app.use(async (ctx,next)=> {
console.log('1.這是第一個中間件01')
await next();
console.log('5.匹配路由完成以后又會返回來執(zhí)行中間件')
}
});
app.use(async (ctx,next)=> {
console.log('2.這是第一個中間件02')
await next();
console.log('4.匹配路由完成以后又會返回來執(zhí)行中間件')
}
});
router.get('/news', async (ctx)=> {
console.log('3.匹配到了這個路由')
ctx.body="這是一個新聞";
})
結(jié)果
1近哟、這是第一個中間件01
2驮审、這是第二個中間件02
3、匹到了news這個路由
4吉执、匹配路由完成以后又會返回來執(zhí)行中間件
5头岔、匹配路由完成以后又會返回來執(zhí)行中間件
koa ejs模板引擎
ejs把nodejs后臺的數(shù)據(jù)渲染到靜態(tài)頁面上
Koa中使用ejs 模板的使用
1.安裝koa-views 和ejs
- 安裝koa-views
npm install --save koa-views - 安裝eis
npm install ejs --save
2.引入koa-views 配置第三方中間件
//第一種方式配置 模板后綴名為ejs
const views = require('koa views');
app.use(views(‘views’,{extension:'ejs'}));//應用ejs模板引擎
//第二種方式配置 模板后綴名為html
const views = require('koa views');
app.use(views(‘views’,{
map:{html:'ejs'}
}));
3.渲染對應的模板引擎
router.get('/add',async (ctx)=>{
let title = 'hello koa2'
await ctx.render(index',{
title:title
})
})
4.Ejs引入模板 引入外部公共文件
<%- include public/header.ejs %>
5.Ejs綁定數(shù)據(jù)
<%=h%>
6.Ejs綁定html的數(shù)據(jù)
let content="<h2>這是一個h2</h2>”
await ctx.render ('/news',{
content: content
})
<%-content%>
7.Ejs模板判斷語句
<% if(true){ %>
true
<%} else{ %>
false
<%} %>
8.Ejs模板中循環(huán)數(shù)據(jù)
<ul >
<%for(var i=0;i<1ist. length;i++) {%>
<1i><%=1ist[i]%></1i>
<%}%>
</u1>
注意:我們需要在每一個路由的render里面都要這染一個公共的數(shù)據(jù)
公共的數(shù)據(jù)放在這個里面,這樣的話在模板的任何地方都可以使用
//寫一個中間件配置公共的信息
app. use (async (ctx,next)=> {
ctx.state.userinfo='張三';
await next();
})
koa 獲取pos提交的數(shù)據(jù)
Koa中koa-bodyparser中間件的使用
1.安裝koa-bodyparser
npm install --save koa-bodyparser
2.安裝引入配置中間件
var Koa = require('koa');
var bodyParser = require('koa-bodyparser');
var app = new Koa();
app.use(bodyParser());
app.use(async ctx=> {
ctx.body = ctx.request. body;
});
3.通過ctx.request.body 獲取post提交的數(shù)據(jù)
//接收post提交的數(shù)據(jù)
router.post('/doAdd',async (ctx)=>{
ctx.body=ctx.request.body;|
})
koa-static靜態(tài)資源中間件
一鼠证、koa-static靜態(tài)資源中間件的功能:
一個http請求訪問web服務靜態(tài)資源峡竣,一般響應結(jié)果有三種情況
- 訪問文本,例如js量九,css适掰,png,jpg荠列,gif
- 訪問靜態(tài)目錄
- 找不到資源类浪,拋出404錯誤
koa-static主要是用于訪問靜態(tài)資源
二、Koa 中koa-static中間件的使用
1肌似、安裝 koa-static
npm install --save koa-static
2费就、引入配置中間件
const static = require('koa-static');
//http://localhost:3000/css/basic.css
//首先去static目錄找,如果能找到返回對應的文件川队,找不到next()
//app.use(static(_dirname+'/static'));
app.use(static('./static'));
koa art-template模板引擎
一力细、Koa2中常見模板引擎的性能對比
適用于 koa 的模板引擎選擇非常多,比如 jade固额、ejs眠蚂、nunjucks、art-template等斗躏。
art-template 是一個簡約逝慧、超快的模板引擎。
它采用作用域預聲明的技術(shù)來優(yōu)化模板渲染速度啄糙,從而獲得接近 JavaScript 極限的運行性能笛臣,并且同時支持 NodeJS 和瀏覽器。
art-template支持ejs的語法隧饼,也可以用自己的類似angular數(shù)據(jù)綁定的語法
官網(wǎng):http://aui.github.io/art-template/
中文文檔: http://aui.github.io/art-template/zh-cn/docs/
1.安裝art-template 和 koa-art-template
npm install --save art-template
npm install --save koa-art-template
2.配置koa-art-template中間件:
const Koa = require('koa');
const render = require('koa-art-template');
const app = new Koa();
render(app, {
root: path.join(__dirname, 'views'),//視圖的位置
extname: '.html',//后綴名
debug: process.env.NODE_ENV !== 'production'//是否開啟調(diào)試模式 true/false
});
router.get('/',async (ctx) {
await ctx.render('index');
});
app.listen(8080);
三沈堡、art-template模板引擎語法
參考:http://aui.github.io/art-template/zh-cn/docs/syntax.html
綁定數(shù)據(jù)
{{list.name}}
綁定html數(shù)據(jù)
{{@list.h}}
條件
{{if num>20}}
大于20
{{else}}
小于20
{{/if}}
循環(huán)數(shù)據(jù)
{{each list.data}}
{{$index}}---{{$value}}
{{/each}}
引入模板
{{include 'public/footer.html'}}
Cookie的使用
一、COOKIE 簡介
- cookie保存在瀏覽器客戶端
- 同一個瀏覽器訪問同一個域共享數(shù)據(jù)
- 保存用戶信息
- 瀏覽器歷史記錄
- 猜你喜歡的功能
- 10天免登陸
- 多個頁面之間的數(shù)據(jù)傳遞
- cookie實現(xiàn)購物車功能
二桑李、Koa2中 Cookie的使用
1踱蛀、Koa中設置Cookie的值
ctx.cookies.set(name, value, [options])
通過 options 設置 cookie name 的 value :
options 名稱 | options 值 |
---|---|
maxAge | 一個數(shù)字表示從 Date.now() 得到的毫秒數(shù) |
expires cookie | 過期的 Date |
path cookie | 路徑, 默認是'/' |
domain cookie | 域名 |
secure | 安全 cookie 默認false窿给,設置成true表示只有 https可以訪問 |
httpOnly | 是否只是服務器可訪問 cookie, 默認是 true |
overwrite | 一個布爾值,表示是否覆蓋以前設置的同名的 cookie (默認是 false). 如果是 true, 在同一個請求中設置相同名稱的所有 Cookie(不管路徑或域)是否在設置此Cookie 時從 Set-Cookie 標頭中過濾掉率拒。 |
path:’/news', /*配置可以訪問的頁面*/
domain:'.baidu.com’ //正常情況不要設置默認就是當前域下面的所有頁面都可以訪問
//
a. baidu. com
b. baidu. com共享cookie的數(shù)據(jù)I
2崩泡、Koa中獲取Cookie的值
ctx.cookies.get('name');
三、Koa中設置中文Cookie
console.log(new Buffer('hello, world!').toStr('base64');
// 轉(zhuǎn)換成base64字符串:aGVsbG8sIHdvcmxkIQ==
console.log(new Buffer('aGVsbG8sIHdvcmxkIQ==', 'base64').toString());
// 還原base64字符串:hello, world!
Koa2中 Cookie的使用教程下載地址:https://pan.baidu.com/s/1KNaA97kGwNhavch5rP_G7w
上面地址失效請訪問:https://www.itying.com/goods-800.html
Koa Session的使用
一猬膨、Koa-Session簡單介紹
session是另一種記錄客戶狀態(tài)的機制角撞,不同的是Cookie保存在客戶端瀏覽器中,而session保存在服務器上勃痴。
二谒所、Session的工作流程
當瀏覽器訪問服務器并發(fā)送第一次請求時,服務器端會創(chuàng)建一個session對象沛申,生成一個類似于key,value的鍵值對劣领, 然后將key(cookie)返回到瀏覽器(客戶)端,瀏覽器下次再訪問時铁材,攜帶key(cookie)尖淘,找到對應的session(value)。 客戶的信息都保存在session中
三著觉、koa-session的使用:
- 安裝 koa-session
npm install koa-session --save
- 引入express-session
const session = require('koa-session');
- 設置官方文檔提供的中間件
app.keys = ['some secret hurr'];//cookie的簽名
const CONFIG = {
key: 'koa:sess', //cookie key (默認 is koa:sess)
maxAge: 86400000, // cookie的過期時間 默認一天
overwrite: true, //是否可以overwrite 沒有效果 (默認default true)
httpOnly: true, //cookie是否只有服務器端可以訪問 (default true)
signed: true, //簽名默認true
rolling: false, //在每次請求時強行設置session村生,這將重置session過期時間(默認:false)
renew: true, //當它快過期的時候重新設置 需要設置 true
};
app.use(session(CONFIG, app));
-
使用
設置值 ctx.session.username = "張三";
獲取值 ctx.session.username
四、Koa中Cookie和Session區(qū)別
cookie數(shù)據(jù)存放在客戶的瀏覽器上饼丘,session數(shù)據(jù)放在服務器上趁桃。
cookie不是很安全,別人可以分析存放在本地的COOKIE并進行COOKIE欺騙
考慮到安全應當使用session肄鸽。session會在一定時間內(nèi)保存在服務器上卫病。當訪問增多,會比較占用你服務器的性能
考慮到減輕服務器性能方面贴捡,應當使用COOKIE忽肛。單個cookie保存的數(shù)據(jù)不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie烂斋。
MongoDB Compass Community可視化工具 (官方提供)
MongoDB Compass是MongoDB官網(wǎng)提供的一個集創(chuàng)建數(shù)據(jù)庫、管理集合和文檔础废、
運行臨時查詢汛骂、評估和優(yōu)化查詢、性能圖表评腺、構(gòu)建地理查詢等功能為一體的MongoDB
可視化管理工具帘瞭。
下載最新的mongodb安裝完成后會自動安裝mongodb可視化工具
https://www.mongodb.com/download-center?imp=nav#community單獨下載mongodb可視化工具
https://www.mongodb.com/products/compass
https://www.mongodb.com/download-center?jimp=nav#compass
一、索引基礎(chǔ)
索引是對數(shù)據(jù)庫表中一列或多列的值進行排序的一一種結(jié)構(gòu)蒿讥,可以讓我們查詢數(shù)據(jù)庫變得
更快蝶念。MongoDB 的索引幾乎與傳統(tǒng)的關(guān)系型數(shù)據(jù)庫一模一樣抛腕,這其中也包括- -些基本的查
詢優(yōu)化技巧。
下面是創(chuàng)建索引的命令 :
db.user.ensureIndex({"username":1})
獲取當前集合的索引:
db.user.getIndexes()
刪除索引的命令是:
db.user.dropIndex( {"username":1})
封裝mongodb DB庫之前的一些準備工作 es6 class類靜態(tài)方法以及單例模式
es6 class類
//定義Person類
class Person {
constructor (name, age) { /*類的構(gòu)造函數(shù)媒殉,實例化的時候執(zhí)行担敌,new的時候執(zhí)行*/
this._name=name;
this._age=age;
}
getName() {
alert(this._ name);
}
setName (name) {
this. name-name
}
}
var p=new Person('張三1',' 20' );//實例化
es6 里面的繼承
class Web extends Person{ //extends關(guān)鍵字繼承了Person
constructor (name,age,sex) {
super(name, age); // super 實例化子類的時候把子類的數(shù)據(jù)傳給父類
this.sex=sex;
}
print() {
console.log(this.sex);
}
}
es6 里面的靜態(tài)方法
class Person {
constructor (name) {
this._ name=name; /*屬 性*/
}
run(){ /*實例方法*/
console.log(this._name);
}
static work(){ /*靜態(tài)方法*/
console.log('這是一個靜態(tài)方法');
}
}
var p=new Person('張三’);
r.run();
Person.work(); //直接調(diào)用靜態(tài)方法
es6 里面的單例
無論實例化多少次 構(gòu)造函數(shù)只執(zhí)行一次
優(yōu)點:有利于提高性能
class Db {
constructor:(){
console.log("實例化會觸發(fā)構(gòu)造函數(shù)’);
this.connect();
}
connect() {
console. log('連接數(shù)據(jù)庫’);
}
find({
console. log('查詢數(shù)據(jù)庫' );
}
static getInstance(){ //單例 判斷有沒有實例,有直接返回
if(!DB.instance){
Db.instance=new new Db();
}
return Db.instance
}
}
var db=new Db()
var mydb1=Db.getInstance()
var mydb2=Db.getInstance()
var mydb2=Db.getInstance()
//調(diào)用靜態(tài)方法只實例化一次
封裝Koa 操作Mongodb數(shù)據(jù)庫的DB類庫
目標
基于官方的node- mongodb-native驅(qū)動廷蓉,封裝一個更小全封、更快、更靈活的DB模塊桃犬,讓我們用nodejs操作Mongodb數(shù)據(jù)庫更方便刹悴、更靈活。
-
安裝mongodb
cnpm install mongodb --save
引入mongodb下面的MongoClient
var MongoClient = require('mongodb').MongoClient;
- 定義數(shù)據(jù)庫連接的地址 以及配置數(shù)據(jù)庫
定義數(shù)據(jù)庫連接的地址
var dburl = 'mongodb://localhost:27017/';
定義數(shù)據(jù)庫的名稱
var dbName = 'koa'
-
nodejs連接數(shù)據(jù)庫
MongoClient.connect(url,function(err,client){
const db = client.db(dbName); 獲取數(shù)據(jù)庫db對象
})
操作數(shù)據(jù)庫
MongoClient.connect(url,function(err,db){
if(err){
console. log(err);
return;
}
//添加數(shù)據(jù)
db.collection('user').insertOne({"name":"張三"},
function(err,result){
if(!err){
console. log(‘添加成功’);
}
db.close(); //關(guān)閉連接
})
//查詢數(shù)據(jù)
var resul t=db.collection('user').find({});
result.toArray((err, result)=>{
console.log(result) ;
})
})
Koa應用生成器以及Koa路由模塊化
一攒暇、koa應用生成器
通過應用koa腳手架生成工具可以快速創(chuàng)建一個基于koa2的應用的骨架土匀,實現(xiàn)路由模塊化
-
全局安裝
npm install koa-generator -g
-
創(chuàng)建項目
koa koa_ demo
-
安裝依賴
cd koa_ demo
npm install -
啟動項目
npm start
Koa2生成器的使用:
https://www.itying.com/koa/start-generator.html
目錄結(jié)構(gòu)如下圖: