将js进行到底:node学习笔记5

HTTP开发之Connect工具集——中间件

继学习node.js的TCP API和HTTP API之后,node.js web开发进入了正轨,但这就好像Java的servlet一样,我们不可能使用最基础得Servlet对象去写网站,我们也不能使用最基本的node http API去写一个完整得网站,我们需要更加强大得工具集,web套件,甚至是web开发框架(诸如Java下的Spring MVC),来提供开发者更人性化得web开发环境。

创建网站的基本任务——为何要有中间件

  1. 独立托管静态文件,诸如:html,css,js,images
  2. 处理错误和不存在的地址
  3. 处理不同类型的请求

如果我们上来就直接用上一章的http模块来做的话,我们需要先实现一个“框架”才能做到一个网站最基本的任务,如果是运用生产环境的话,我们希望有这样的一个“框架”——connect工具集,最好称它为工具集,他离所谓的“框架”依旧有点差距。

Connect是基于http API之上的,也就是基于node http模块写出来的,方便web开发者使用,他提供了一些工具方法能够上一些重复性的工作便于实现,让开发者更加专注于应用的功能业务。

Connect已经是十分基础的node web开发工具集,在实际开发中很少看到,以后回介绍稍微高级点的express(对于实际开发来说依然很基础)

特别注意:《了不起的node.js》一书中的代码和connect版本过时了,如果使用最新版的connect需要参照如下方法使用!

导入Connect等中间件模块

Connect模块并非node.js的原生模块,需要引入外部模块

同时还要导入“serve-static”,“content-disposition”提供静态文件访问支持

最终完整package.json:

{
    "name":"node-connect",
    "version":"0.0.1",
    "description":"Use connect to create a website",
    "dependencies":{
        "connect":"latest",
        "serve-static":"latest",
        "content-disposition":"latest"
    }
}

node npm包搜索管理网站:https://www.npmjs.com/

注:除了connect外,还导入了serve-static,这个包原本属于connect集合,后官方独立出来了,《了不起的node.js》使用的是1.8.x版本的connect(太老了)还包含着static中间件,这里使用了3.0.0+的版本,则需要额外导入这个静态中间件模块。

这些是官网独立的中间件(Connect/Express负责管理)

将不同功能的中间件从connect独立出来是一件好事,方便管理维护!(对于开发者需要注意查看更新)

npm install

引用connect模块

//引入connect模块
var connect = require("connect");
//依然需要引入http模块
var http = require("http")
//依然使用http模块创建服务器
http.createServer().listen(3000);

connect现在是http中间件,如果使用本文最新的connect版本就不能出现《了不起的node.js》一书中的connect.createServer(),因为connect已经移除了这个方法!!!

createServer交给了http模块去做,充分体现了connect是中间件的特性,而不是代替http!

依然使用http.createServer()创建http服务器!!!

使用serve-static中间件托管静态文件

node本身不像nginx,apache,他不是一个完整的http服务器,而是一个语言解析器。

通过对node.js API的开发,可以构建类似nginx一样的功能,负责提供用户静态页面,这就需要用到serve-static中间件

首先serve-static中间件原本属于connect中间件,现在已经独立出来了,也就说其实和connect关系已经不大了,但我依然将两者放在一回中解说。

静态文件指的是:html,css,图片,js等等

在项目目录下新建一个views目录,存放静态html文件

新建index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>hello world</h1>
</body>
</html>

index.js返回静态页面代码:

//引入http模块
var http = require("http");
//引入serveStatic模块
var serveStatic = require(‘serve-static‘)
var finalhandler = require(‘finalhandler‘);

var serve = serveStatic(__dirname+‘/views‘,{‘index‘:[‘index.html‘,‘index.htm‘]});

http.createServer(function(req,res){
    serve(req,res,finalhandler(req,res));
}).listen(3000);

finalhandler是什么?

作用是友好处理找不到页面访问不到URL的异常和错误,如果删除,用户访问非法地址将会导致node抛出异常停止工作。

访问首页之外的页面?

views下创建一个hello.html,直接在浏览器地址后面+“/hello.html”即可访问这个页面。

访问图片文件?

如何提示下载文件?

var contentDisposition = require(‘content-disposition‘)
var finalhandler = require(‘finalhandler‘)
var http = require(‘http‘)
var serveStatic = require(‘serve-static‘)

var serve = serveStatic(__dirname+‘/files‘, {
  ‘index‘: false,
  ‘setHeaders‘: setHeaders
})

//强制下载
function setHeaders (res, path) {
  res.setHeader(‘Content-Disposition‘, contentDisposition(path))
}

http.createServer(function onRequest (req, res) {
  serve(req, res, finalhandler(req, res))
}).listen(3000);

新建一个files目录,下载的文件放在里面即可。

到此,serve-static中间件简化了开发者托管静态文件的代码,我们不必向上一章那样使用fs+http方式去自己实现输出流文件给浏览器客户端。

使用connect中间件处理不同的请求

在上一回中,如果要对用户不同访问给出对应的返回,我们需要在同一个createServer中不停的写if...else if....else if...else....if.........来判断,这样显得代码十分冗余,而且根本无法把所有情况写清楚,也无法扩展,且根本无法维护。

上一回的部分代码:

    //请求为图片
    if(req.method == ‘GET‘ && req.url.substr(-4)==".jpg"){
        fs.stat(__dirname+req.url,function(err,stat){
            if(err || !stat.isFile()){
                res.writeHead(404);
                res.end("找不到图片");
                return;
            }
            serve(__dirname+req.url,‘application/x-jpg‘);
        });
    }else if(req.method=="GET" && req.url==‘/‘){
    //请求为html文件
        serve(__dirname+‘/form.html‘,‘text/html‘);
    }else{
        res.writeHead(404);
        res.end("网址丢了");
        return;
    }

接下来使用connect重写这些代码:(代码是基于static-serve那块修改过来的)

//下载文件模块
var contentDisposition = require(‘content-disposition‘)
//不需要finalhandler
//var finalhandler = require(‘finalhandler‘)
//http模块创建http服务器必须
var http = require(‘http‘)
//静态文件托管中间件
var serveStatic = require(‘serve-static‘)
//connect工具集
var connect = require("connect");
var app = connect();

app.use(function(req,res,next){
    //任何请求都会打印!是必然执行的一步
    console.error(‘%s %s‘,req.method,req.url)
    next();
});

//图片显示
app.use("/images",function(req,res,next){
    serveStatic(__dirname+"/images")(req,res,next);
});
//下载文件
app.use("/files",function(req,res,next){
    serveStatic(__dirname+"/files",{‘index‘:false,‘setHeaders‘:setHeaders})(req,res,next);
});

//最终处理,所有next都执行不通后到达此处
app.use(function(req,res,next){
    res.writeHead(404);
    res.end(‘404 Not Found‘)
    //没有next了,这是最终方法,返回404 not found就行了
});

//强制下载函数
function setHeaders (res, path) {
  res.setHeader(‘Content-Disposition‘, contentDisposition(path))
}
//建立http服务器
http.createServer(app).listen(3000);

注意到我们依然需要http模块来建立http服务器,然后引入了connect模块,以及之前的serve-static和content-disposition。

这一段代码实际上是把上一回分类请求处理和这一回静态文件托管强强联手了

如果说serve-static这个中间件解决的是静态文件托管的话,那么connect中间件其实是解决了路由,请求定向的控制。这样我们不再需要通过手写的if...else来判断用户请求了什么类型的文件。

next()函数

这个函数在connect中扮演了十分重要的角色,作用:将不同种类的请求线性的串联在一行,每一个app.use()其实类似于原来我们写的if...else语句,next就是在处理不了的情况下,执行另一个app.use(),这样只要回掉函数做不了就抛给下一个做,这样不停的“甩锅”,最终谁都做不了就有一个最终函数,开发者需要建立这样的最终函数,里面没有next()了,说明到最后一步了,必须返回错误给用户看了。我们这里最终函数是一个404错误反馈。

use()函数

第一个参数可以给定一个请求的目录,相对于node执行的项目目录,相当于浏览器网址后面第一个“/”后面的参数。

原文地址:https://www.cnblogs.com/devilyouwei/p/8439387.html

时间: 2024-08-07 23:40:22

将js进行到底:node学习笔记5的相关文章

Js脚本之jQuery学习笔记(1)

Js脚本之jQuery学习笔记(1) 一.javascript基础 单行注释 多行注释 /* */ 数据类型 数值型 字符串型 布尔型 空值 未定义值 转义字符 函数定义:1234567891011121314<head><script language="javascript"function test(m){var xixi="嘻嘻"alert("这是javascript")document.write(xixi + m)}

《JS高程》事件学习笔记

事件:文档或浏览器窗口中发生的一些特定的交互瞬间,也即用户或浏览器自身执行的某种动作. ------------------------------------------------------------------------------------------------------------- 一.事件流 事件流:描述的是页面中接收事件的顺序. IE:事件冒泡流,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档): NetScape:事件捕获流,即不太具体的节

node 学习笔记1 router路由

1. var express = require('express'); var app = express(); app.get('/', function(req, res){ res.send('hello world'); }); app.listen(3000); 一个最为常见的 路由 2. var admin = express(); admin.get('/', function (req, res) { console.log(admin.mountpath); // [ '/a

将js进行到底:node学习笔记4

使用Node做web开发 废话:说起web开发,这真的算是我的老本行了,从进入计算机领域我习得的第一门语言便是php,到后来公司使用的ASP.NET平台,再到学校强推的JavaEE平台,后来自学了一点ruby on rails平台,一直到现在node.js做毕设终究还是没有绕出web开发这个大坑!(其实我一直想做嵌入式的,有段时间疯狂迷恋c语言来着==|||). HTTP与TCP 上一回使用node.js的NET(TCP)模块开发了一个聊天室demo.单纯用到了原始的TCP协议,可以说TCP是H

node学习笔记(1)--简介及安装Node.js开发环境

简介 Node.js是让Javascript脱离浏览器运行在服务器的一个平台,不是语言: Node.js采用的Javascript引擎是来自Google Chrome的V8:运行在浏览器外不用考虑头疼的Javascript兼容性问题 采用单线程.异步IO与事件驱动的设计来实现高并发(异步事件也在一定程度上增加了开发和调试的难度): Node.js内建一个HTTP服务器,所以对于网站开发来说是一个好消息: 主页:http://nodejs.org/  英文API:http://nodejs.org

node+webpack环境搭建 vue.js 2.0 基础学习笔记

npm install -g vue //全局安装vue npm install -g webpack //全局安装webpack npm install -g vue-cli //全局安装vue-cli //可用淘宝镜像 npm=>cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org生成项目 vue init webpack my-first-vue-project //生成项目名为my-first-vue-pr

node学习笔记

1.Node,可以让javascript运行在服务器端的平台. 是一个为实时Web(Real-time Web)应用开发而诞生的平台.充分考虑了实时响应,超大规模数据要求下架构. 2.摒弃了传统平台依靠多线程来实现高并发的设计思路,而采用了单线程.异步式I/O,事件驱动式的程序设计模型. 不仅带来了巨大的性能提升,还减少了多线程程序设计复杂性,进而提高了开发效率. 3.单线程事件驱动的异步I/O. 单线程事件驱动的异步I/O比传统的多线程阻塞式I/O到底好在哪里:简而言这,异步式I/O少了多线程

Node学习笔记(四):gulp+express+io.socket部署angularJs2(填坑篇)

这篇就先暂停下上篇博客--你画我猜的进度,因为在做这个游戏的时候,想采用最新的ng2技术,奈何坑是一片又一片,这边就先介绍下环境部署和填坑史 既然要用ng2,首先要拿到资源,我这边用的是angularJs2 beta版的,网上的资源有两种,一个是文件全压缩版的.min.js版的另一个就是一大堆乱七八糟的js文件,主要是ng2已经完全采用TypeScript,加之对es6的支持,所以需要引入一大堆兼容,编译文件 这边刚好特别手欠想学学gulp,于是开搞配置gulp环境,压缩所有的js文件成一个mi

node 学习笔记

以下笔记默认安装完成node 及npm 1.安装express 新版本的express-generator已经独立出来,全局安装这个包就ok. npm install express-generator -gd 2.新建一个文件夹并进入 3.执行express -e 初始化项目 4.npm install 安装项目依赖包 5.npm start 启动项目 6.为省去每次调试都要手动kill process然后重启项目的麻烦 可以安装superviser views文件夹下 .ejs 改为.htm