72、JavaScript Node koa入门

创建koa2工程

 

首先,我们创建一个目录hello-koa并作为工程目录用VS Code打开。然后,我们创建app.js,输入以下代码:

  1. // 导入koa,和koa 1.x不同,在koa2中,我们导入的是一个class,因此用大写的Koa表示:
  2. const Koa = require('koa');
  3. // 创建一个Koa对象表示web app本身:
  4. const app = new Koa();
  5. // 对于任何请求,app将调用该异步函数处理请求:
  6. app.use(async (ctx, next) => {
  7.     await next();
  8.     ctx.response.type = 'text/html';
  9.     ctx.response.body = '<h1>Hello, koa2!</h1>';
  10. });
  11. // 在端口3000监听:
  12. app.listen(3000);
  13. console.log('app started at port 3000...');

 

对于每一个http请求,koa将调用我们传入的异步函数来处理:

  1. async (ctx, next) => {
  2.     await next();
  3.     // 设置response的Content-Type:
  4.     ctx.response.type = 'text/html';
  5.     // 设置response的内容:
  6.     ctx.response.body = '<h1>Hello, koa2!</h1>';
  7. }

 

其中,参数ctx是由koa传入的封装了requestresponse的变量,我们可以通过它访问request和response,next是koa传入的将要处理的下一个异步函数。

 

上面的异步函数中,我们首先用await next();处理下一个异步函数,然后,设置responseContent-Type和内容。

 

由async标记的函数称为异步函数,在异步函数中,可以用await调用另一个异步函数,这两个关键字将在ES7中引入。

 

现在我们遇到第一个问题:koa这个包怎么装,app.js才能正常导入它?

 

方法一:可以用npm命令直接安装koa。先打开命令提示符,务必把当前目录切换到hello-koa这个目录,然后执行命令:

C:\...\hello-koa> npm install koa@2.0.0

npm会把koa2以及koa2依赖的所有包全部安装到当前目录的node_modules目录下。

 

方法二:在hello-koa这个目录下创建一个package.json,这个文件描述了我们的hello-koa工程会用到哪些包。完整的文件内容如下:

  1. {
  2. "name""hello-koa2",
  3. "version""1.0.0",
  4. "description""Hello Koa 2 example with async",
  5. "main""app.js",
  6. "scripts": {
  7. "start""node app.js"
  8. },
  9. "keywords": [
  10. "koa",
  11. "async"
  12. ],
  13. "author""Michael Liao",
  14. "license""Apache-2.0",
  15. "repository": {
  16. "type""git",
  17. "url""https://github.com/michaelliao/learn-javascript.git"
  18. },
  19. "dependencies": {
  20. "koa""2.0.0"
  21. }
  22. }

其中,dependencies描述了我们的工程依赖的包以及版本号。其他字段均用来描述项目信息,可任意填写。

 

然后,我们在hello-koa目录下执行npm install就可以把所需包以及依赖包一次性全部装好:

C:\...\hello-koa> npm install

很显然,第二个方法更靠谱,因为我们只要在package.json正确设置了依赖,npm就会把所有用到的包都装好。

 

注意,任何时候都可以直接删除整个node_modules目录,因为用npm install命令可以完整地重新下载所有依赖。并且,这个目录不应该被放入版本控制中。

 

现在,我们的工程结构如下:

hello-koa/

|

+- .vscode/

| |

| +- launch.json <-- VSCode 配置文件

|

+- app.js <-- 使用koa的js

|

+- package.json <-- 项目描述文件

|

+- node_modules/ <-- npm安装的所有依赖包

 

紧接着,我们在package.json中添加依赖包:

  1. "dependencies": {
  2. "koa""2.0.0"
  3. }

 

然后使用npm install命令安装后,在VS Code中执行app.js,调试控制台输出如下:

node --debug-brk=40645 --nolazy app.js

Debugger listening on port 40645

app started at port 3000...

 

我们打开浏览器,输入http://localhost:3000,即可看到效果:koa-browser

 

还可以直接用命令node app.js在命令行启动程序,或者用npm start启动。npm start命令会让npm执行定义在package.json文件中的start对应命令:

  1. "scripts": {
  2. "start""node app.js"
  3. }
  4. koa middleware

让我们再仔细看看koa的执行逻辑。核心代码是:

  1. app.use(async (ctx, next) =&gt; {
  2. await next();
  3. ctx.response.type = 'text/html';
  4. ctx.response.body = '&lt;h1&gt;Hello, koa2!&lt;/h1&gt;';
  5. });

 

每收到一个http请求,koa就会调用通过app.use()注册的async函数,并传入ctxnext参数。

 

我们可以对ctx操作,并设置返回内容。但是为什么要调用await next()?

原因是koa把很多async函数组成一个处理链,每个async函数都可以做一些自己的事情,然后用await next()来调用下一个async函数。我们把每个async函数称为middleware,这些middleware可以组合起来,完成很多有用的功能。

 

例如,可以用以下3个middleware组成处理链,依次打印日志,记录处理时间,输出HTML:

app.use(async (ctx, next) => {

console.log(`${ctx.request.method} ${ctx.request.url}`); // 打印URL

await next(); // 调用下一个middleware

});

app.use(async (ctx, next) => {

const start = new Date().getTime(); // 当前时间

await next(); // 调用下一个middleware

const ms = new Date().getTime() - start; // 耗费时间

console.log(`Time: ${ms}ms`); // 打印耗费时间

});

app.use(async (ctx, next) => {

await next();

ctx.response.type = 'text/html';

ctx.response.body = '<h1>Hello, koa2!</h1>';

});

middleware的顺序很重要,也就是调用app.use()的顺序决定了middleware的顺序。

 

此外,如果一个middleware没有调用await next(),会怎么办?答案是后续的middleware将不再执行了。这种情况也很常见,例如,一个检测用户权限的middleware可以决定是否继续处理请求,还是直接返回403错误:

app.use(async (ctx, next) => {

if (await checkUserPermission(ctx)) {

await next();

} else {

ctx.response.status = 403;

}

});

 

理解了middleware,我们就已经会用koa了!

 

最后注意ctx对象有一些简写的方法,例如ctx.url相当于ctx.request.urlctx.type相当于ctx.response.type

 

文件源码:app.js、package.json

 

1、app.js

  1. const Koa = require('koa');
  2. const app = new Koa();
  3. app.use(async (ctx, next) => {
  4.     const start = new Date().getTime();
  5.     await next();
  6.     const ms = new Date().getTime() - start;
  7.     console.log(`${ctx.request.method} ${ctx.request.url}: ${ms}ms`);
  8.     ctx.response.set('X-Response-Time', `${ms}ms`);
  9. });
  10. app.use(async (ctx, next) => {
  11.     await next();
  12.     ctx.response.type = 'text/html';
  13.     ctx.response.body = '<h1>Hello, koa2!</h1>';
  14. });
  15. app.listen(3000);
  16. console.log('app started at port 3000...');

 

2、package.json

  1. {
  2.     "name""hello-koa",
  3.     "version""1.0.0",
  4.     "description""Hello Koa 2 example with async",
  5.     "main""app.js",
  6.     "scripts": {
  7.         "start""node --use_strict app.js"
  8.     },
  9.     "keywords": [
  10.         "koa",
  11.         "async"
  12.     ],
  13.     "author""Michael Liao",
  14.     "license""Apache-2.0",
  15.     "repository": {
  16.         "type""git",
  17.         "url""https://github.com/michaelliao/learn-javascript.git"
  18.     },
  19.     "dependencies": {
  20.         "koa""2.0.0"
  21.     }
  22. }
付杰

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: