±à¼ÍƼö: |
±¾ÎÄÀ´×Ôcsdn£¬ÎÄÕ½éÉÜÁËkoa2Ô´ÂëµÄ´óÌå¿ò¼Ü½á¹¹¡¢ÊµÏÖkoa¿ò¼ÜÐèÒªµÄËĸö´óÄ£¿éµÈÏà¹ØÄÚÈÝ¡£ |
|
koaÊÇÒ»¸ö»ùÓÚnodeʵÏÖµÄÒ»¸öеÄweb¿ò¼Ü£¬ËüÊÇÓÉexpress¿ò¼ÜµÄÔ°àÈËÂí´òÔìµÄ¡£ËüµÄÌØµãÊÇÓÅÑÅ¡¢¼ò½à¡¢±í´ïÁ¦Ç¿¡¢×ÔÓɶȸߡ£Ëü¸üexpressÏà±È£¬ËüÊÇÒ»¸ö¸üÇáÁ¿µÄnode¿ò¼Ü£¬ÒòΪËüËùÓй¦Äܶ¼Í¨¹ý²å¼þʵÏÖ£¬ÕâÖÖ²å°ÎʽµÄ¼Ü¹¹Éè¼ÆÄ£Ê½£¬ºÜ·ûºÏunixÕÜѧ¡£
koa¿ò¼ÜÏÖÔÚ¸üе½ÁË2.x°æ±¾£¬±¾ÎÄ´ÓÁ㿪ʼ£¬ÑÐò½¥½ø£¬½²½âkoa2µÄ¿ò¼ÜÔ´Âë½á¹¹ºÍʵÏÖÔÀí£¬Õ¹Ê¾ºÍÏê½âkoa2¿ò¼ÜÔ´ÂëÖеö×îÖØÒªµÄ¸ÅÄȻºóÊÖ°ÑÊ̴ֽó¼ÒÇ××ÔʵÏÖÒ»¸ö¼òÒ×µÄkoa2¿ò¼Ü£¬°ïÖú´ó¼ÒѧϰºÍ¸üÉî²ã´ÎµÄÀí½âkoa2£¬¿´Íê±¾ÎÄÒÔºó£¬ÔÙÈ¥¶ÔÕÕkoa2µÄÔ´Âë½øÐв鿴£¬ÏàÐÅÄãµÄ˼·½«»á·Ç³£µÄ˳³©¡£
±¾ÎÄËùÓõĿò¼ÜÊÇkoa2£¬Ëü¸úkoa1²»Í¬£¬koa1ʹÓõÄÊÇgenerator+co.jsµÄÖ´Ðз½Ê½£¬¶økoa2ÖÐʹÓÃÁËasync/await£¬Òò´Ë±¾ÎĵĴúÂëºÍdemoÐèÒªÔËÐÐÔÚnode
8°æ±¾¼°ÆäÒÔÉÏ£¬Èç¹û¶ÁÕßµÄnode°æ±¾½ÏµÍ£¬½¨ÒéÉý¼¶»òÕß°²×°babel-cli£¬ÓÃÆäÖеÄbabel-nodeÀ´ÔËÐб¾ÎÄÉæ¼°µ½µÄ´úÂë¡£
koaÔ´Âë½á¹¹

ÉÏͼÊÇkoa2µÄÔ´ÂëĿ¼½á¹¹µÄlibÎļþ¼Ð£¬libÎļþ¼ÐÏ·Å×ÅËĸökoa2µÄºËÐÄÎļþ£ºapplication.js¡¢context.js¡¢request.js¡¢response.js¡£
application.js
application.jsÊÇkoaµÄÈë¿ÚÎļþ£¬ËüÏòÍâµ¼³öÁË´´½¨classʵÀýµÄ¹¹Ô캯Êý£¬Ëü¼Ì³ÐÁËevents£¬ÕâÑù¾Í»á¸³Óè¿ò¼Üʼþ¼àÌýºÍʼþ´¥·¢µÄÄÜÁ¦¡£application»¹±©Â¶ÁËһЩ³£ÓõÄapi£¬±ÈÈçtoJSON¡¢listen¡¢useµÈµÈ¡£
listenµÄʵÏÖÔÀíÆäʵ¾ÍÊǶÔhttp.createServer½øÐÐÁËÒ»¸ö·â×°£¬ÖصãÊÇÕâ¸öº¯ÊýÖд«ÈëµÄcallback£¬ËüÀïÃæ°üº¬ÁËÖмä¼þµÄºÏ²¢£¬ÉÏÏÂÎĵĴ¦Àí£¬¶ÔresµÄÌØÊâ´¦Àí¡£
useÊÇÊÕ¼¯Öмä¼þ£¬½«¶à¸öÖмä¼þ·ÅÈëÒ»¸ö»º´æ¶ÓÁÐÖУ¬È»ºóͨ¹ýkoa-composeÕâ¸ö²å¼þ½øÐеݹé×éºÏµ÷ÓÃÕâһЩÁеÄÖмä¼þ¡£
context.js
Õⲿ·Ö¾ÍÊÇkoaµÄÓ¦ÓÃÉÏÏÂÎÄctx,Æäʵ¾ÍÒ»¸ö¼òµ¥µÄ¶ÔÏó±©Â¶£¬ÀïÃæµÄÖØµãÔÚdelegate£¬Õâ¸ö¾ÍÊÇ´úÀí£¬Õâ¸ö¾ÍÊÇΪÁË¿ª·¢Õß·½±ã¶øÉè¼ÆµÄ£¬±ÈÈçÎÒÃÇÒª·ÃÎÊctx.repsponse.statusµ«ÊÇÎÒÃÇͨ¹ýdelegate£¬¿ÉÒÔÖ±½Ó·ÃÎÊctx.status·ÃÎʵ½Ëü¡£
request.js¡¢response.js
ÕâÁ½²¿·Ö¾ÍÊǶÔÔÉúµÄres¡¢reqµÄһЩ²Ù×÷ÁË£¬´óÁ¿Ê¹ÓÃes6µÄgetºÍsetµÄһЩÓï·¨£¬È¥È¡headers»òÕßÉèÖÃheaders¡¢»¹ÓÐÉèÖÃbodyµÈµÈ£¬ÕâЩ¾Í²»Ïêϸ½éÉÜÁË£¬ÓÐÐËȤµÄ¶ÁÕß¿ÉÒÔ×ÔÐп´Ô´Âë¡£
ʵÏÖkoa2µÄËÄ´óÄ£¿é
ÉÏÎļòÊöÁËkoa2Ô´ÂëµÄ´óÌå¿ò¼Ü½á¹¹£¬½ÓÏÂÀ´ÎÒÃÇÀ´ÊµÏÖÒ»¸ökoa2µÄ¿ò¼Ü£¬±ÊÕßÈÏΪÀí½âºÍʵÏÖÒ»¸ökoa¿ò¼ÜÐèҪʵÏÖËĸö´óÄ£¿é£¬·Ö±ðÊÇ£º
·â×°node http server¡¢´´½¨KoaÀ๹Ô캯Êý
¹¹Ôìrequest¡¢response¡¢context¶ÔÏó
Öмä¼þ»úÖÆºÍ°þÑó´ÐÄ£Ð͵ÄʵÏÖ
´íÎó²¶»ñºÍ´íÎó´¦Àí
ÏÂÃæÎÒÃǾÍÖðÒ»·ÖÎöºÍʵÏÖ¡£
Ä£¿éÒ»£º·â×°node http serverºÍ´´½¨KoaÀ๹Ô캯Êý
ÔĶÁkoa2µÄÔ´ÂëµÃÖª£¬ÊµÏÖkoaµÄ·þÎñÆ÷Ó¦ÓúͶ˿ڼàÌý£¬Æäʵ¾ÍÊÇ»ùÓÚnodeµÄÔÉú´úÂë½øÐÐÁË·â×°£¬ÈçÏÂͼµÄ´úÂë¾ÍÊÇͨ¹ýnodeÔÉú´úÂëʵÏֵķþÎñÆ÷¼àÌý¡£
let http = require('http');
let server = http.createServer((req, res) =>
{
res.writeHead(200);
res.end('hello world');
});
server.listen(3000, () => {
console.log('listenning on 3000');
}); |
ÎÒÃÇÐèÒª½«ÉÏÃæµÄnodeÔÉú´úÂë·âװʵÏÖ³ÉkoaµÄģʽ£º
const http =
require('http');
const Koa = require('koa');
const app = new Koa();
app.listen(3000); |
ʵÏÖkoaµÄµÚÒ»²½¾ÍÊǶÔÒÔÉϵÄÕâ¸ö¹ý³Ì½øÐзâ×°£¬Îª´ËÎÒÃÇÐèÒª´´½¨application.jsʵÏÖÒ»¸öApplicationÀàµÄ¹¹Ô캯Êý£º
let http = require('http');
class Application {
constructor() {
this.callbackFunc;
}
listen(port) {
let server = http.createServer(this.callback());
server.listen(port);
}
use(fn) {
this.callbackFunc = fn;
}
callback() {
return (req, res) => {
this.callbackFunc(req, res);
};
}
}
module.exports = Application; |
È»ºó´´½¨example.js£¬ÒýÈëapplication.js£¬ÔËÐзþÎñÆ÷ʵÀýÆô¶¯¼àÌý´úÂ룺
let Koa = require('./application');
let app = new Koa();
app.use((req, res) => {
res.writeHead(200);
res.end('hello world');
});
app.listen(3000, () => {
console.log('listening on 3000');
}); |
ÏÖÔÚÔÚä¯ÀÀÆ÷ÊäÈëlocalhost:3000¼´¿É¿´µ½ä¯ÀÀÆ÷ÀïÏÔʾ¡°hello world¡±¡£ÏÖÔÚµÚÒ»²½ÎÒÃÇÒѾÍê³ÉÁË£¬¶Ôhttp
server½øÐÐÁ˼òµ¥µÄ·â×°ºÍ´´½¨ÁËÒ»¸ö¿ÉÒÔÉú³ÉkoaʵÀýµÄÀàclass£¬Õâ¸öÀàÀﻹʵÏÖÁËapp.useÓÃÀ´×¢²áÖмä¼þºÍ×¢²á»Øµ÷º¯Êý£¬app.listenÓÃÀ´¿ªÆô·þÎñÆ÷ʵÀý²¢´«Èëcallback»Øµ÷º¯Êý£¬µÚһģ¿éÖ÷ÒªÊÇʵÏÖµäÐ͵Äkoa·ç¸ñºÍ´îºÃÁËÒ»¸ökoaµÄ¼òµ¥µÄ¼Ü×Ó¡£½ÓÏÂÀ´ÎÒÃÇ¿ªÊ¼±àдºÍ½²½âµÚ¶þÄ£¿é¡£
Ä£¿é¶þ£º¹¹Ôìrequest¡¢response¡¢context¶ÔÏó
ÔĶÁkoa2µÄÔ´ÂëµÃÖª£¬ÆäÖÐcontext.js¡¢request.js¡¢response.jsÈý¸öÎļþ·Ö±ðÊÇrequest¡¢response¡¢contextÈý¸öÄ£¿éµÄ´úÂëÎļþ¡£context¾ÍÊÇÎÒÃÇÆ½Ê±Ð´koa´úÂëʱµÄctx£¬ËüÏ൱ÓÚÒ»¸öÈ«¾ÖµÄkoaʵÀýÉÏÏÂÎÄthis£¬ËüÁ¬½ÓÁËrequest¡¢responseÁ½¸ö¹¦ÄÜÄ£¿é£¬²¢ÇÒ±©Â¶¸økoaµÄʵÀýºÍÖмä¼þµÈ»Øµ÷º¯ÊýµÄ²ÎÊýÖУ¬Æðµ½³ÐÉÏÆôϵÄ×÷Óá£
request¡¢responseÁ½¸ö¹¦ÄÜÄ£¿é·Ö±ð¶ÔnodeµÄÔÉúrequest¡¢response½øÐÐÁËÒ»¸ö¹¦Äܵķâ×°£¬Ê¹ÓÃÁËgetterºÍsetterÊôÐÔ£¬»ùÓÚnodeµÄ¶ÔÏóreq/res¶ÔÏó·â×°koaµÄrequest/response¶ÔÏó¡£ÎÒÃÇ»ùÓÚÕâ¸öÔÀí¼òµ¥ÊµÏÖÒ»ÏÂrequest.js¡¢response.js£¬Ê×ÏÈ´´½¨request.jsÎļþ£¬È»ºóдÈëÒÔÏ´úÂ룺
let url = require('url');
module.exports = {
get query() {
return url.parse(this.req.url, true).query;
}
}; |
ÕâÑùµ±ÄãÔÚkoaʵÀýÀïʹÓÃctx.queryµÄʱºò£¬¾Í»á·µ»Øurl.parse(this.req.url,
true).queryµÄÖµ¡£¿´Ô´Âë¿ÉÖª£¬»ùÓÚgetterºÍsetter£¬ÔÚrequest.jsÀﻹ·â×°ÁËheader¡¢url¡¢origin¡¢pathµÈ·½·¨£¬¶¼ÊǶÔÔÉúµÄrequestÉÏÓÃgetterºÍsetter½øÐÐÁË·â×°£¬±ÊÕß²»ÔÙÕâÀïһһʵÏÖ¡£
½ÓÏÂÀ´ÎÒÃÇʵÏÖresponse.jsÎļþ´úÂëÄ£¿é£¬ËüºÍrequestÔÀíÒ»Ñù£¬Ò²ÊÇ»ùÓÚgetterºÍsetter¶ÔÔÉúresponse½øÐÐÁË·â×°£¬ÄÇÎÒÃǽÓÏÂÀ´Í¨¹ý¶Ô³£ÓõÄctx.bodyºÍctx.statusÕâ¸öÁ½¸öÓï¾äµ±×öÀý×Ó¼òÊöÒ»ÏÂÈç¹ûʵÏÖkoaµÄresponseµÄÄ£¿é£¬ÎÒÃÇÊ×ÏÈ´´½¨ºÃresponse.jsÎļþ£¬È»ºóÊäÈëÏÂÃæµÄ´úÂ룺
module.exports
= {
get body() {
return this._body;
},
set body(data) {
this._body = data;
},
get status() {
return this.res.statusCode;
},
set status(statusCode) {
if (typeof statusCode !== 'number') {
throw new Error('something wrong!');
}
this.res.statusCode = statusCode;
}
}; |
ÒÔÉÏ´úÂëʵÏÖÁ˶ÔkoaµÄstatusµÄ¶ÁÈ¡ºÍÉèÖ㬶ÁÈ¡µÄʱºò·µ»ØµÄÊÇ»ùÓÚÔÉúµÄresponse¶ÔÏóµÄstatusCodeÊôÐÔ£¬¶øbodyµÄ¶ÁÈ¡ÔòÊǶÔthis._body½øÐжÁдºÍ²Ù×÷¡£ÕâÀï¶Ôbody½øÐвÙ×÷²¢Ã»ÓÐʹÓÃÔÉúµÄthis.res.end£¬ÒòΪÔÚÎÒÃDZàдkoa´úÂëµÄʱºò£¬»á¶Ôbody½øÐжà´ÎµÄ¶ÁÈ¡ºÍÐ޸ģ¬ËùÒÔÕæÕý·µ»Øä¯ÀÀÆ÷ÐÅÏ¢µÄ²Ù×÷ÊÇÔÚapplication.jsÀï½øÐзâ×°ºÍ²Ù×÷¡£
ÏÖÔÚÎÒÃÇÒѾʵÏÖÁËrequest.js¡¢response.js£¬»ñÈ¡µ½ÁËrequest¡¢response¶ÔÏóºÍËûÃǵķâ×°µÄ·½·¨£¬È»ºóÎÒÃÇ¿ªÊ¼ÊµÏÖcontext.js£¬contextµÄ×÷ÓþÍÊǽ«request¡¢response¶ÔÏó¹ÒÔØµ½ctxµÄÉÏÃæ£¬ÈÃkoaʵÀýºÍ´úÂëÄÜ·½±ãµÄʹÓõ½request¡¢response¶ÔÏóÖеķ½·¨¡£ÏÖÔÚÎÒÃÇ´´½¨context.jsÎļþ£¬ÊäÈëÈçÏ´úÂ룺
let proto = {};
function delegateSet(property, name) {
proto.__defineSetter__(name, function (val) {
this[property][name] = val;
});
}
function delegateGet(property, name) {
proto.__defineGetter__(name, function () {
return this[property][name];
});
}
let requestSet = [];
let requestGet = ['query'];
let responseSet = ['body', 'status'];
let responseGet = responseSet;
requestSet.forEach(ele => {
delegateSet('request', ele);
});
requestGet.forEach(ele => {
delegateGet('request', ele);
});
responseSet.forEach(ele => {
delegateSet('response', ele);
});
responseGet.forEach(ele => {
delegateGet('response', ele);
});
module.exports = proto; |
context.jsÎļþÖ÷ÒªÊǶԳ£ÓõÄrequestºÍresponse·½·¨½øÐйÒÔØºÍ´úÀí£¬Í¨¹ýcontext.queryÖ±½Ó´úÀíÁËcontext.request.query£¬context.bodyºÍcontext.status´úÀíÁËcontext.response.bodyÓëcontext.response.status¡£¶øcontext.request£¬context.responseÔò»áÔÚapplication.jsÖйÒÔØ
±¾À´¿ÉÒÔÓüòµ¥µÄsetterºÍgetterÈ¥ÉèÖÃÿһ¸ö·½·¨£¬µ«ÊÇÓÉÓÚcontext¶ÔÏó¶¨Òå·½·¨±È½Ï¼òµ¥ºÍ¹æ·¶£¬ÔÚkoaÔ´ÂëÀï¿ÉÒÔ¿´µ½£¬koaÔ´ÂëÓõÄÊÇdefineSetterºÍdefineSetterÀ´´úÌæsetter/getterÿһ¸öÊôÐԵĶÁÈ¡ÉèÖã¬ÕâÑù×öÖ÷ÒªÊÇ·½±ãÍØÕ¹ºÍ¾«¼òÁËд·¨£¬µ±ÎÒÃÇÐèÒª´úÀí¸ü¶àµÄresºÍreqµÄ·½·¨µÄʱºò£¬¿ÉÒÔÏòcontext.jsÎļþÀïÃæµÄÊý×é¶ÔÏóÀïÃæÌí¼Ó¶ÔÓ¦µÄ·½·¨ÃûºÍÊôÐÔÃû¼´¿É¡£
ĿǰΪֹ£¬ÎÒÃÇÒѾµÃµ½ÁËrequest¡¢response¡¢contextÈý¸öÄ£¿é¶ÔÏóÁË£¬½ÓÏÂÀ´¾ÍÊǽ«request¡¢responseËùÓз½·¨¹ÒÔØµ½contextÏ£¬ÈÃcontextʵÏÖËüµÄ³ÐÉÏÆôϵÄ×÷Óã¬ÐÞ¸Äapplication.jsÎļþ£¬Ìí¼ÓÈçÏ´úÂ룺
let http = require('http');
let context = require('./context');
let request = require('./request');
let response = require('./response');
createContext(req, res) {
let ctx = Object.create(this.context);
ctx.request = Object.create(this.request);
ctx.response = Object.create(this.response);
ctx.req = ctx.request.req = req;
ctx.res = ctx.response.res = res;
return ctx;
} |
¿ÉÒÔ¿´µ½£¬ÎÒÃÇÌí¼ÓÁËcreateContextÕâ¸ö·½·¨£¬Õâ¸ö·½·¨Êǹؼü£¬Ëüͨ¹ýObject.create´´½¨ÁËctx£¬²¢½«requestºÍresponse¹ÒÔØµ½ÁËctxÉÏÃæ£¬½«ÔÉúµÄreqºÍres¹ÒÔØµ½ÁËctxµÄ×ÓÊôÐÔÉÏ£¬Íù»Ø¿´Ò»ÏÂcontext/request/response.jsÎļþ£¬¾ÍÄÜÖªµÀµ±Ê±Ê¹ÓõÄthis.res»òÕßthis.responseÖ®ÀàµÄÊÇ´ÓÄÄÀïÀ´µÄÁË£¬ÔÀ´ÊÇÔÚÕâ¸öcreateContext·½·¨ÖйÒÔØµ½Á˶ÔÓ¦µÄʵÀýÉÏ£¬¹¹½¨ÁËÔËÐÐʱÉÏÏÂÎÄctxÖ®ºó£¬ÎÒÃǵÄapp.use»Øµ÷º¯Êý²ÎÊý¾Í¶¼»ùÓÚctxÁË¡£
Ä£¿éÈý£ºÖмä¼þ»úÖÆºÍ°þÑó´ÐÄ£Ð͵ÄʵÏÖ
ĿǰΪֹÎÒÃÇÒѾ³É¹¦ÊµÏÖÁËÉÏÏÂÎÄcontext¶ÔÏó¡¢ ÇëÇórequest¶ÔÏóºÍÏìÓ¦response¶ÔÏóÄ£¿é£¬»¹²îÒ»¸ö×îÖØÒªµÄÄ£¿é£¬¾ÍÊÇkoaµÄÖмä¼þÄ£¿é£¬koaµÄÖмä¼þ»úÖÆÊÇÒ»¸ö°þÑó´ÐʽµÄÄ£ÐÍ£¬¶à¸öÖмä¼þͨ¹ýuse·Å½øÒ»¸öÊý×é¶ÓÁÐÈ»ºó´ÓÍâ²ã¿ªÊ¼Ö´ÐУ¬Óöµ½nextºó½øÈë¶ÓÁÐÖеÄÏÂÒ»¸öÖмä¼þ£¬ËùÓÐÖмä¼þÖ´ÐÐÍêºó¿ªÊ¼»ØÖ¡£¬Ö´ÐжÓÁÐÖÐ֮ǰÖмä¼þÖÐδִÐеĴúÂ벿·Ö£¬Õâ¾ÍÊǰþÑó´ÐÄ£ÐÍ£¬koaµÄÖмä¼þ»úÖÆ¡£
koaµÄ°þÑó´ÐÄ£ÐÍÔÚkoa1ÖÐʹÓõÄÊÇgenerator + co.jsȥʵÏֵģ¬koa2ÔòʹÓÃÁËasync/await
+ PromiseȥʵÏֵ쬽ÓÏÂÀ´ÎÒÃÇ»ùÓÚasync/await + PromiseȥʵÏÖkoa2ÖеÄÖмä¼þ»úÖÆ¡£Ê×ÏÈ£¬¼ÙÉèµ±koaµÄÖмä¼þ»úÖÆÒѾ×öºÃÁË£¬ÄÇôËüÊÇÄܳɹ¦ÔËÐÐÏÂÃæ´úÂëµÄ£º
let Koa = require('../src/application');
let app = new Koa();
app.use(async (ctx, next) => {
console.log(1);
await next();
console.log(6);
});
app.use(async (ctx, next) => {
console.log(2);
await next();
console.log(5);
});
app.use(async (ctx, next) => {
console.log(3);
ctx.body = "hello world";
console.log(4);
});
app.listen(3000, () => {
console.log('listenning on 3000');
}); |
ÔËÐгɹ¦ºó»áÔÚÖÕ¶ËÊä³ö123456£¬ÄǾÍÄÜÑéÖ¤ÎÒÃǵÄkoaµÄ°þÑó´ÐÄ£ÐÍÊÇÕýÈ·µÄ¡£½ÓÏÂÀ´ÎÒÃÇ¿ªÊ¼ÊµÏÖ£¬ÐÞ¸Äapplication.jsÎļþ£¬Ìí¼ÓÈçÏ´úÂ룺
compose() {
return async ctx => {
function createNext(middleware, oldNext) {
return async () => {
await middleware(ctx, oldNext);
}
}
let len = this.middlewares.length;
let next = async () => {
return Promise.resolve();
};
for (let i = len - 1; i >= 0; i--) {
let currentMiddleware = this.middlewares[i];
next = createNext(currentMiddleware, next);
}
await next();
};
}
callback() {
return (req, res) => {
let ctx = this.createContext(req, res);
let respond = () => this.responseBody(ctx);
let onerror = (err) => this.onerror(err, ctx);
let fn = this.compose();
return fn(ctx);
};
} |
koaͨ¹ýuseº¯Êý£¬°ÑËùÓеÄÖмä¼þpushµ½Ò»¸öÄÚ²¿Êý×é¶ÓÁÐthis.middlewaresÖУ¬°þÑó´ÐÄ£ÐÍÄÜÈÃËùÓеÄÖмä¼þÒÀ´ÎÖ´ÐУ¬Ã¿´ÎÖ´ÐÐÍêÒ»¸öÖмä¼þ£¬Óöµ½next()¾Í»á½«¿ØÖÆÈ¨´«µÝµ½ÏÂÒ»¸öÖмä¼þ£¬ÏÂÒ»¸öÖмä¼þµÄnext²ÎÊý£¬°þÑó´ÐÄ£Ð͵Ä×î¹Ø¼ü´úÂëÊÇcomposeÕâ¸öº¯Êý£º
compose() {
return async ctx => {
function createNext(middleware, oldNext) {
return async () => {
await middleware(ctx, oldNext);
}
}
let len = this.middlewares.length;
let next = async () => {
return Promise.resolve();
};
for (let i = len - 1; i >= 0; i--) {
let currentMiddleware = this.middlewares[i];
next = createNext(currentMiddleware, next);
}
await next();
};
} |
createNextº¯ÊýµÄ×÷ÓþÍÊǽ«ÉÏÒ»¸öÖмä¼þµÄnextµ±×ö²ÎÊý´«¸øÏÂÒ»¸öÖмä¼þ£¬²¢ÇÒ½«ÉÏÏÂÎÄctx°ó¶¨µ±Ç°Öмä¼þ£¬µ±Öмä¼þÖ´ÐÐÍ꣬µ÷ÓÃnext()µÄʱºò£¬Æäʵ¾ÍÊÇÈ¥Ö´ÐÐÏÂÒ»¸öÖмä¼þ¡£
for (let i =
len - 1; i >= 0; i--) {
let currentMiddleware = this.middlewares[i];
next = createNext(currentMiddleware, next);
} |
ÉÏÃæÕâ¶Î´úÂëÆäʵ¾ÍÊÇÒ»¸öÁ´Ê½·´ÏòµÝ¹éÄ£Ð͵ÄʵÏÖ£¬iÊÇ´Ó×î´óÊý¿ªÊ¼Ñ»·µÄ£¬½«Öмä¼þ´Ó×îºóÒ»¸ö¿ªÊ¼·â×°£¬Ã¿Ò»´Î¶¼Êǽ«×Ô¼ºµÄÖ´Ðк¯Êý·â×°³Énextµ±×öÉÏÒ»¸öÖмä¼þµÄnext²ÎÊý£¬ÕâÑùµ±Ñ»·µ½µÚÒ»¸öÖмä¼þµÄʱºò£¬Ö»ÐèÒªÖ´ÐÐÒ»´Înext()£¬¾ÍÄÜÁ´Ê½µÄµÝ¹éµ÷ÓÃËùÓÐÖмä¼þ£¬Õâ¸ö¾ÍÊÇkoa°þÑó´ÐµÄºËÐÄ´úÂë»úÖÆ¡£
µ½ÕâÀïÎÒÃÇ×ܽáÒ»ÏÂÉÏÃæËùÓаþÑó´ÐÄ£ÐÍ´úÂëµÄÁ÷³Ì£¬Í¨¹ýuse´«½øÀ´µÄÖмä¼þÊÇÒ»¸ö»Øµ÷º¯Êý£¬»Øµ÷º¯ÊýµÄ²ÎÊýÊÇctxÉÏÏÂÎĺÍnext£¬nextÆäʵ¾ÍÊÇ¿ØÖÆÈ¨µÄ½»½Ó°ô£¬nextµÄ×÷ÓÃÊÇÍ£Ö¹ÔËÐе±Ç°Öмä¼þ£¬½«¿ØÖÆÈ¨½»¸øÏÂÒ»¸öÖмä¼þ£¬Ö´ÐÐÏÂÒ»¸öÖмä¼þµÄnext()֮ǰµÄ´úÂ룬µ±ÏÂÒ»¸öÖмä¼þÔËÐеĴúÂëÓöµ½ÁËnext()£¬ÓֻὫ´úÂëÖ´ÐÐȨ½»¸øÏÂϸöÖмä¼þ£¬µ±Ö´Ðе½×îºóÒ»¸öÖмä¼þµÄʱºò£¬¿ØÖÆÈ¨·¢Éú·´×ª£¬¿ªÊ¼»ØÍ·È¥Ö´ÐÐ֮ǰËùÓÐÖмä¼þÖÐÊ£ÏÂδִÐеĴúÂ룬ÕâÕû¸öÁ÷³ÌÓеãÏñÒ»¸öαµÝ¹é£¬µ±×îÖÕËùÓÐÖмä¼þÈ«²¿Ö´ÐÐÍêºó£¬»á·µ»ØÒ»¸öPromise¶ÔÏó£¬ÒòΪÎÒÃǵÄcomposeº¯Êý·µ»ØµÄÊÇÒ»¸öasyncµÄº¯Êý£¬asyncº¯ÊýÖ´ÐÐÍêºó»á·µ»ØÒ»¸öPromise£¬ÕâÑùÎÒÃǾÍÄܽ«ËùÓеÄÖмä¼þÒì²½Ö´ÐÐͬ²½»¯£¬Í¨¹ýthen¾Í¿ÉÒÔÖ´ÐÐÏìÓ¦º¯ÊýºÍ´íÎó´¦Àíº¯Êý¡£
µ±Öмä¼þ»úÖÆ´úÂëдºÃÁËÒÔºó£¬ÔËÐÐÎÒÃǵÄÉÏÃæµÄÀý×Ó£¬ÒѾÄÜÊä³ö123456ÁË£¬ÖÁ´Ë£¬ÎÒÃǵÄkoaµÄ»ù±¾¿ò¼ÜÒѾ»ù±¾×öºÃÁË£¬²»¹ýÒ»¸ö¿ò¼Ü²»ÄÜֻʵÏÖ¹¦ÄÜ£¬ÎªÁË¿ò¼ÜºÍ·þÎñÆ÷ʵÀýµÄ½¡×³£¬»¹ÐèÒª¼ÓÉÏ´íÎó´¦Àí»úÖÆ¡£
Ä£¿éËÄ£º´íÎó²¶»ñºÍ´íÎó´¦Àí
ҪʵÏÖÒ»¸ö»ù´¡¿ò¼Ü£¬´íÎó´¦ÀíºÍ²¶»ñ±Ø²»¿ÉÉÙ£¬Ò»¸ö½¡×³µÄ¿ò¼Ü£¬±ØÐë±£Ö¤ÔÚ·¢Éú´íÎóµÄʱºò£¬Äܹ»²¶»ñµ½´íÎóºÍÅ׳öµÄÒì³££¬²¢·´À¡³öÀ´£¬½«´íÎóÐÅÏ¢·¢Ë͵½¼à¿ØÏµÍ³ÉϽøÐз´À¡£¬Ä¿Ç°ÎÒÃÇʵÏֵļòÒ×koa¿ò¼Ü»¹Ã»ÓÐÄÜʵÏÖÕâÒ»µã£¬ÎÒÃǽÓϼÓÉÏ´íÎó´¦ÀíºÍ²¶»ñµÄ»úÖÆ¡£
throw new Error('oooops'); |
»ùÓÚÏÖÔڵĿò¼Ü£¬Èç¹ûÖмä¼þ´úÂëÖгöÏÖÈçÉÏ´íÎóÒì³£Å׳ö£¬ÊDz¶»ñ²»µ½´íÎóµÄ£¬ÕâʱºòÎÒÃÇ¿´Ò»ÏÂapplication.jsÖеÄcallbackº¯ÊýµÄreturn·µ»Ø´úÂ룬ÈçÏ£º
return fn(ctx).then(respond); |
¿ÉÒÔ¿´µ½£¬fnÊÇÖмä¼þµÄÖ´Ðк¯Êý£¬Ã¿Ò»¸öÖмä¼þ´úÂë¶¼ÊÇÓÉasync°ü¹ü×ŵ쬶øÇÒÖмä¼þµÄÖ´Ðк¯Êýcompose·µ»ØµÄÒ²ÊÇÒ»¸öasyncº¯Êý£¬ÎÒÃǸù¾Ýes7µÄ¹æ·¶ÖªµÀ£¬async·µ»ØµÄÊÇÒ»¸öpromiseµÄ¶ÔÏóʵÀý£¬ÎÒÃÇÈç¹ûÏëÒª²¶»ñpromiseµÄ´íÎó£¬Ö»ÐèҪʹÓÃpromiseµÄcatch·½·¨£¬¾Í¿ÉÒÔ°ÑËùÓеÄÖмä¼þµÄÒ쳣ȫ²¿²¶»ñµ½£¬Ð޸ĺócallbackµÄ·µ»Ø´úÂëÈçÏ£º
return fn(ctx).then(respond).catch(onerror); |
ÏÖÔÚÎÒÃÇÒѾʵÏÖÁËÖмä¼þµÄ´íÎóÒì³£²¶»ñ£¬µ«ÊÇÎÒÃÇ»¹È±ÉÙ¿ò¼Ü²ã·¢Éú´íÎóµÄ²¶»ñ»úÖÆ£¬ÎÒÃÇÏ£ÍûÎÒÃǵķþÎñÆ÷ʵÀýÄÜÓдíÎóʼþµÄ¼àÌý»úÖÆ£¬Í¨¹ýonµÄ¼àÌýº¯Êý¾ÍÄܶ©ÔĺͼàÌý¿ò¼Ü²ãÃæÉϵĴíÎó£¬ÊµÏÖÕâ¸ö»úÖÆ²»ÄÑ£¬Ê¹ÓÃnodejsÔÉúeventsÄ£¿é¼´¿É£¬eventsÄ£¿é¸øÎÒÃÇÌṩÁËʼþ¼àÌýonº¯ÊýºÍʼþ´¥·¢emitÐÐΪº¯Êý£¬Ò»¸ö·¢Éäʼþ£¬Ò»¸ö¸ºÔð½ÓÊÕʼþ£¬ÎÒÃÇÖ»ÐèÒª½«koaµÄ¹¹Ô캯Êý¼Ì³ÐeventsÄ£¿é¼´¿É£¬¹¹ÔìºóµÄα´úÂëÈçÏ£º
let EventEmitter
= require('events');
class Application extends EventEmitter {} |
¼Ì³ÐÁËeventsÄ£¿éºó£¬µ±ÎÒÃÇ´´½¨koaʵÀýµÄʱºò£¬¼ÓÉÏon¼àÌýº¯Êý£¬´úÂëÈçÏ£º
let app = new
Koa();
app.on('error', err => {
console.log('error happends: ', err.stack);
}); |
ÕâÑùÎÒÃǾÍʵÏÖÁË¿ò¼Ü²ãÃæÉϵĴíÎóµÄ²¶»ñºÍ¼àÌý»úÖÆÁË¡£×ܽáһϣ¬´íÎó´¦ÀíºÍ²¶»ñ£¬·ÖÖмä¼þµÄ´íÎó´¦Àí²¶»ñºÍ¿ò¼Ü²ãµÄ´íÎó´¦Àí²¶»ñ£¬Öмä¼þµÄ´íÎó´¦ÀíÓÃpromiseµÄcatch£¬¿ò¼Ü²ãÃæµÄ´íÎó´¦ÀíÓÃnodejsµÄÔÉúÄ£¿éevents£¬ÕâÑùÎÒÃǾͿÉÒÔ°ÑÒ»¸ö·þÎñÆ÷ʵÀýÉϵÄËùÓеĴíÎóÒ쳣ȫ²¿²¶»ñµ½ÁË¡£ÖÁ´Ë£¬ÎÒÃǾÍÍêÕûʵÏÖÁËÒ»¸öÇáÁ¿°æµÄkoa¿ò¼ÜÁË¡£
½áβ
ǰΪֹ£¬ÎÒÃÇÒѾʵÏÖÁËÒ»¸öÇáÁ¿°æµÄkoa¿ò¼ÜÁË£¬ÎÒÃÇʵÏÖÁË·â×°node http server¡¢´´½¨KoaÀ๹Ô캯Êý¡¢¹¹Ôìrequest¡¢response¡¢context¶ÔÏó¡¢Öмä¼þ»úÖÆºÍ°þÑó´ÐÄ£Ð͵ÄʵÏÖ¡¢´íÎó²¶»ñºÍ´íÎó´¦ÀíÕâËĸö´óÄ£¿é£¬Àí½âÁËÕâ¸öÇáÁ¿°ækoaµÄʵÏÖÔÀí£¬ÔÙÈ¥¿´koa2µÄÔ´Â룬Äã¾Í»á·¢ÏÖÒ»Çж¼»íÈ»¿ªÀÊ£¬koa2µÄÔ´ÂëÎ޷ǾÍÊÇÔÚÕâ¸öÇáÁ¿°æ»ù´¡ÉϼÓÁ˺ܶ๤¾ßº¯ÊýºÍϸ½ÚµÄ´¦Àí£¬ÏÞÓÚÆª·ù±ÊÕ߾Ͳ»ÔÙÒ»Ò»½éÉÜÁË¡£
|