node.js 移动前端开发平台 reactWeb前端之路

Nodejs笔记

2017-01-31  本文已影响529人  AkaTBS

Node基本

  1. node的最大特性莫过于基于事件驱动的非阻塞I/O模型。
  2. node通过事件驱动的方式处理请求,无须为每一个请求创建额外的对应线程,可以省掉创建线程和销毁线程的开销,同时操作系统在调度任务时因为线程较少,上下文切换的代价很低。这使得服务器能够有条不紊地处理请求,即使在大量连接的情况下,也不受线程上下文切换开销的影响,这是Node高性能的一个原因。Apache会为每个请求启动一个线程,每个线程会占用一定内存,并发量较大时会缓慢。Nginx也使用和node一样的事件驱动方式处理请求。
  3. node对引入过的模块都会进行缓存,以减少二次引入时的开销,node缓存的是编译和执行后的对象。不论是核心模块还是文件模块,require( )方法对相同模块的二次加载都一律采用缓存优先的方式,这是第一优先级的。不同之处在于核心模块的缓存检查先于文件模块的缓存检查。
  4. 事件轮询:从本质上来说,node会先注册事件,随后不停地询问内核这些时间是否已经分发。当事件分发时,对应的回调函数就会被触发,然后继续执行下去。如果没有事件触发,则继续执行其他代码,直到有新事件时,再去执行对应的回调函数。
  5. 在程序中定义配置项如app.set(“photo”,__dirname+’/public/photos’)后就可以在各种环境下任意改变此目录。
  6. 当node接收到从浏览器发来的http请求时,底层的TCP连接会分配一个文件描述符。随后,如果客户端向服务器发送数据,node就会收到该文件描述符上的通知,然后触发JavaScript的回调函数。
  7. 对于阻塞式I/O线程在执行中遇到磁盘读写或者数据库通讯,网络通讯这种耗时比较多的时候,操作系统将会剥夺此线程的CPU资源,并暂停此线程,转而去执行别的线程。异步式I/O则针对所有操作采取不阻塞的方法,当线程遇到I/O操作时将操作发送给操作系统,然后接着执行下一个操作,当操作系统执行完I/O操作之后,将以事件的方式通知执行I/O的线程,线程会在特定的时候执行这个事件。这一切的前提就是系统需要一个时间循环,以不断地去查询有没有未处理的事件,然后交给预处理。对比与阻塞I/O,异步模型极大提高了web服务器的并发性。
  8. buffer是一个表示固定内存分配的全局对象(即放到缓冲区的字节数需要提前确定)
  9. node的HTTP服务器是构建于node TCP服务器之上的,即node中的HTTP.server继承自net.server(net为TCP模块)。TCP的首要特性是它面向连接。
  10. Node中的管道可以让数据流动到指定目的地(即WriteableStream)读取一个文件并写入到另一个文件中,利用pipe()作为连接,ReadableStream.pipe(WriteableStream).HTTP请求中在客户端request就是一个WriteableStream,response为Readablestream,而在服务器端则相反。
  11. node与操作系统交互的工具
    • 全局的process对象————包含当前进程的相关信息,如传参和当前设定的环境变量
    • fs模块————包含底层的ReadStream和WriteStream类。
    • child_process模块————繁衍子进程的底层和高层接口,以及一种繁衍带有双向信息传递通道node实例的特殊办法。
  12. node内置了调试器,控制台输入node debug app.js可以分步调试程序,n(下一步)、s(步入)、o(步出)。n会跨过当前行:调试器会执行这一行,但如果指令调用了其他函数,在这些函数执行完后才把控制权交还。s与之不同,如果调用其他函数会进入函数内部逐步执行。o允许跳出当前正在执行的函数。
  13. 也可以使用node探查器node-inspector,可以在浏览器内逐步调试。

node的异步I/O

Buffer对象

var chunks = [];
var size = 0;
res.on('data', function (chunk) {
chunks.push(chunk);
size += chunk.length;
});
res.on('end', function () {
var data = null;
switch(chunks.length) {
case 0: data = new Buffer(0);
break;
case 1: data = chunks[0];
break;
default:
data = new Buffer(size);
for (var i = 0, pos = 0, l = chunks.length; i < l; i++) {
var chunk = chunks[i];
chunk.copy(data, pos);
pos += chunk.length;
}
break;
}
});
```

函数式编程

高阶函数

偏函数

网络通信

REST API

webSocket

HTTPS

Node使用

  1. 在node中定义了静态文件app.use(express.static(path))之后如果要用里面数据可以直接使用以/开头的静态文件相对路径。

  2. node删除file使用fs.unlink( )!

  3. node中fs.stat( )系统调用获取文件的相关信息,比如修改时间、字节数等,如果文件不存在fs.stat()会在err.code中放入ENOOENT作为响应。

  4. app.use('/api',api.auth)这是挂载点,即任何以/api开头的请求路径名和HTTP谓词都会导致这个中间件被调用。

  5. node中引入crypto模块用于加密

    function sha1(str){
    

var md5sum = crypto.createHash("sha1");
md5sum.update(str);
str = md5sum.digest("hex");
return str;
}

```
  1. 模块内引用路径时一定要使用绝对路径,借助于全局变量__dirname与__filename来使用。因为当主函数使用模块时若是相对路径则以主函数作为参考。

  2. 标准库组件url可以补全地址url.resolve(主站url,href)。

  3. node中的全局函数process.argv为一个argument的数组索引为零的储存的是node所在文件夹,索引为1的是当前执行文件路径,后面的索引为在命令行启动node时传入的参数。

  4. 模块导出时用module.exports={函数名}的形式,导入模块时即使在同一目录下也需要在开头加“./文件名.js”若不加./则优先在内置模块中寻找,然后是在node_modules文件夹中寻找。

  5. 绝大部分node异步API接收的回调函数,第一个参数都是错误对象或者是null。

  6. Event模块时node对‘发布/订阅’模式的实现,其中提供了一个EventEmitter对象,核心事件就是事件的触发与事件监听功能的封装。

var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter; //初始化对象
emitter.on(‘自定义事件名’,function(){}) //绑定事件
emitter.emit(‘事件名’,‘回调函数的参数’) // 触发事件
```

  1. 使用net.creatServer( function(socket){})时候回调函数传回来的是一个socket对象,可以通过给socket对象setEncoding来设置接收到的流的显示方式。socket.on(‘data’,回调函数)来给socket绑定接受到数据时触发的事件。
  2. fs.createReadStream('fire.jpg').pipe(respond);在http中通过流的方式给页面中传图片。
  3. node中http会将所有主机名后面的内容放入request.url中.
  4. node提供querystring的模块,该模块含有一个.parse( )方法,传入参数如“q=1”的字符串返回一个{q:1}的对象。这个解析处理方式和Node解析header消息的方法类似,node将http请求数据中的header信息从字符串解析成一个方便处理的header对象。同样可以使用querystring.stringfy({q:1})将对象转为字符串。
  5. 在http的请求中一般通过给respond绑定data事件来获取返回的数据,绑定end事件等待数据获取完后执行相应操作。
  6. node在设置登录页面时,如果用到了第三方认证如微博QQ等登录可以使用passport模块,方便配置各种类型的OAuth。
  7. express客户端使用socket.io要引入socket.io给客户端写的js文件<script src='/socket.io/socket.io.js'></script>
  8. express中使用socket.io模块,如果要群发信息则需要每个客户端都加入到同一房间内,使用socket.join(‘房间名’);来加入房间,然后使用socket.to(‘房间名’).emit(‘event’,fn)来广播消息,消息默认只对除当前客户端之外的所有客户端发送,如果还要对当前客户端发送则再加上socket.emit(‘event’,fn)。可以利用socket.rooms来查看客户端所在的房间,返回一个对象。一个客户端可以在多个房间,第一个房间与客户端的id相同,是一个随机的字符串,如果要针对某个客户端单独发消息可以用to指向客户端所对应的专属房间。
  9. express中路由和中间件的添加顺序至关重要,如果把404处理器放在所有路由上面,首页和相关页面就无法显示。自己编写中间件时如果方法后面没有调用next()则不会再执行之后的中间件。使用app.use(‘/url’,中间件),第一个参数表示当url前缀与之匹配是才会调用后面的中间件。
  10. bodyParser()组件用于解析POST请求,它提供了req.body属性,可以用来解析注册信息如JSON、x-www-form-urlencoded(HTML表单的默认值)和multipart/form-data请求。如果是multipart/form-data请求,如文件上传,则还有req.files对象。
  11. query()组件主要用于解析GET请求,它提供req.query对象将url中的GET数据转化成一个对象存在req.query中。
  12. cheerio组件为一个 Node.js 版的 jquery,用来从网页中以 css selector 取数据,使用方式跟 jquery 一样一样的。在爬虫应用中使用superagent.get()得到网页的数据srea之后利用cheerio 来将数据解析var $ = cheerio.load(sres.text);之后通过$(‘.’)方式来获取DOM。
  13. 一定要注意superagent使用的是异步请求,会在发送去请求后继续执行下面代码而非在获得请求结果后。
  14. 利用eventproxy组件针对多个异步请求统一处理回调函数,无深度嵌套。用来检测多个异步操作是否完成,完成之后,会自动调用处理函数,并将抓取到的数据当参数传过来。
  15. 当你需要去多个源(一般是小于 10 个)汇总数据的时候,用 eventproxy 方便;当你需要用到队列,需要控制并发数,或者你喜欢函数式编程思维时,使用 async做异步处理。
  16. nodemon这个库是专门调试时候使用的,它会自动检测node.js 代码的改动,然后帮你自动重启应用。在调试时可以完全用 nodemon 命令代替 node 命令。$ nodemon app.js 启动应用。
  17. 上传大型文件时可以使用formidable的流式解析器,它可以随着数据块的上传接收它们并呈现特定的部分这种方式不仅快,还不会因为需要大量的缓冲而导致内存膨胀,即便像视频这种大型文件,也不会把进程压垮。
  18. 管理用户密码文件时所谓加Salt,就是加点“佐料”。当用户首次提供密码时(通常是注册时),由系统自动往这个密码里加一些“Salt值”,这个值是由系统随机生成的,并且只有系统知道。然后再散列。而当用户登录时,系统为用户提供的代码撒上同样的“Salt值”,然后散列,再比较散列值,已确定密码是否正确。这样,即便两个用户使用了同一个密码,由于系统为它们生成的salt值不同,他们的散列值也是不同的。即便黑客可以通过自己的密码和自己生成的散列值来找具有特定密码的用户,但这个几率太小了(密码和salt值都得和黑客使用的一样才行)。参看express的auth示例。
  19. Post/Redirect/Get(PRG)模式是一个常用的web程序设计模式。在这种模式中,用户请求表单,用HTTP/POST请求表单数据,然后用户被重定向到另外一个web页面上。被重定向到哪里取决于表单数据是否有效。如果表单数据无效,程序会让用户回到表单页面。如果表单数据有效,程序会让用户到新的页面中。PRG模式主要是为了防止表单的重复提交。
  20. 在express中用户被重定向后,res.locals中的内容会被重置。Server传来消息最好存在会话变量中。res.message函数可以吧消息添加到任何Express请求的会话变量中。
  21. express.response对象是Express给相应对象的原型,向这个对象中添加属性意味着所有的中间件和路由都能访问它们。
  22. 使用res.redirect()时第一个参数可以填HTTP的Status Code,301重定向是“永久”的,意味着浏览器会缓存重定向目标。如果使用301重定向并试图第二次提交表单,浏览器会绕过整个处理程序并直接进入相应页面。使用303重定向不会缓存重定向目标。默认是302重定向。
  23. http中结束一次会话后记得调用res.end()结束请求,否则客户端将一直处于等待状态。

Async库

Async库是为了处理nodejs中的异步任务,同样也可以设置任务的同步执行流程。

使用async调用的函数必须是有一个callback参数,并在函数执行完后调用callback(null, "done!");第一个参数是error参数。如果任何一个函数向它的回调函数中传了一个error,则后面的函数都不会被执行,并且将会立刻会将该error以及已经执行了的函数的结果,传给series中最后那个callback。

  1. series(tasks, [callback]) (多个函数依次执行,之间没有数据交换)
  2. waterfall(tasks, [callback]) (多个函数依次执行,且前一个的输出为后一个的输入)
  3. parallel(tasks, [callback]) (多个函数并行执行)
  4. auto(tasks, [callback]) (多个函数有依赖关系,有的并行执行,有的依次执行)
  5. whilst(test, fn, callback)(用可于异步调用的while)

BasicAuth库

路由参数

app.get(/staff/:name,function(){}) 

node中路由系统会将参数值放入req.params.name中。

ejs模板

        <ul>  
          <% names.forEach(function(name){ %>  
            <li><%= name %></li>  
          <% }) %>  
        </ul>  

options

```

cache:true, //是否对结果进行缓存(需要filename)
filename:"path", //cache的key,用于include指令中
scope:"this", //指定函数执行的上下文对象
debug:true, //输出生成的函数体
compileDebug:false, //为false时,debug指令不会被编译
client:"", //返回独立的编译后的函数
open:"<%", //指定开标签
close:"%>", //指定闭标签
```

ejs.render(str, {
users: [
{ name: 'tj' },
{ name: 'mape' },
{ name: 'guillermo' }
]
});
// 结果是:<p>Tj, Mape, Guillermo</p>

child_process模块中的spawn和exec方法

爬虫

  1. __VIEWSTATE
    a) ViewState是ASP.NET中用来保存WEB控件回传时状态值一种机制。在WEB窗体(FORM)的设置为runat="server",这个窗体(FORM)会被附加一个隐藏的属性_VIEWSTATE。_VIEWSTATE中存放了所有控件在ViewState中的状态值。 ViewState是类Control中的一个域,其他所有控件通过继承Control来获得了ViewState功能。它的类型是system.Web.UI.StateBag,一个名称/值的对象集合。
    b) 当请求某个页面时,ASP.NET把所有控件的状态序列化成一个字符串,然后做为窗体的隐藏属性送到客户端。当客户端把页面回传时,ASP.NET分析回传的窗体属性,并赋给控件对应的值。
  2. __EVENTVALIDATION
    __EVENTVALIDATION只是用来验证事件是否从合法的页面发送,只是一个数字签名,所以一般很短。“id”属性为“__EVENTVALIDATION”的隐藏字段是ASP.NET 2.0的新增的安全措施。该功能可以阻止由潜在的恶意用户从浏览器端发送的未经授权的请求.
    为了确保每个回发和回调事件来自于所期望的用户界面元素,ASP.NET运行库将在事件中添加额外的验证层。服务器端通过检验表单提交请求的内容,将其与“id”属性为“__EVENTVALIDATION”隐藏字段中的信息进行匹配。根据匹配结果来验证未在浏览器端添加额外的输入字段(有可能为用户在浏览器端恶意添加的字段),并且该值是在服务器已知的列表中选择的。ASP.NET运行库将在生成期间创建事件验证字段,而这是最不可能获取该信息的时刻。像视图状态一样,事件验证字段包含散列值以防止发生浏览器端篡改。
    说明:“id”属性为“__EVENTVALIDATION”隐藏字段一般在表单的最下方,如果表单在浏览器端尚未解析完毕时,用户提交数据有可能导致验证失败。__EVENTVALIDATION与__VIEWSTATE一般可以在浏览器页面源代码中找到,作为form中被隐藏的标签,与其他数据一同提交。
  3. 使用superagent得到response的cookie: JSON.stringify(res.header["set-cookie"]);
  4. 针对superagent获取的网页乱码的情况,superagent-charset扩展了superagent的功能,使其可以手动指定编码功能。
  5. MD5加密是一种不可逆加密算法,使用MD5加密时相同内容以字符串传入与数字传入得到的结果不同。
上一篇 下一篇

猜你喜欢

热点阅读