Nodejs笔记1

来源:互联网 发布:ubuntu root用户提权 编辑:程序博客网 时间:2024/06/06 07:27

第一讲


  1. NodeJs是一个让JavaScript运行在服务端的开发平台;
  2. Node.js能做什么;
    JavaScript是由客户端而生,node.Js为网络而生;
    具有复杂的逻辑的网站;
    基于社交网络的大web的应用;
    web socket服务器
    Tcp/Udp套接字应用程序;
    命令行工具;
    交互式终端程序;

3.异步式I/O与事件驱动;
NodeJs最大的特性就是采用异步式I/O与事件驱动的 架构设计;对于高并发的解决方案,传统的架构是多线程模型,也就是为每个业务逻辑业务提供一个系统线程,通过系统线程切换来弥补同步式I/O调用是的时间开销。Nodejs使用单线程模型,在执行过程中会维护一个事件队列,程序在执行时,在进入时间循环等待下一个事件到来;

第二讲:


  1. cd nodeDemo
    node 进入编译模式; node test.js (Utf8编码需要)
  2. 命令行 node 指令 进入编译模式;
    node -v 产看版本号;
    node -e eval
    node -e “console.log(‘hello’)”
  3. 安装实时调试插件;不用重启了node server.js ,节约了调试时间;
    npm -g install supervisor

博客园地址http://www.cnblogs.com/pigtail/archive/2013/01/08/2851056.html

第三讲 : Nodejs 异步式IO与事件式编程


第四讲: 回到函数与事件


  1. 异步式读取文件
    `

     // 异步式读取文件 var fs= require('fs'); fs.readFile('app.js','utf-8',function(error,data){ if(error){ console.log( '读取文件失败!'+ error ) }else{ console.log(data + '我是读的文件内容,我是IO操作,我通过事件循环后输出') } });console.log('异步式读取,我是end,我先输出')

    `

  2. 同步时读取文件
    `
    // 同步时读取文件

    var fs = require('fs');var data = fs.readFileSync('test.js','utf-8');console.log('我是同步时读取文件,我先输出'+ data);console.log('我是同步时读取文件,我第二个输出');`
  3. 异步式IO把请求发送给了操作系统,然后接着执行后边的语句,执行完毕后,进入事件循环,当fs接收到IO请求弯沉的事件后,事件会主动调用回调函数,完成后续的工作;同步则是阻塞是等待完成后,继续执行;

二. 事件
1. 普通事件的使用

    `/*     * @Author: Marte    * @Date:   2017-04-15 10:25:52    * @Last Modified by:   Marte    * @Last Modified time: 2017-04-15 10:31:44    */    // 事件    var eventEmitter = require('events').EventEmitter;    var event = new eventEmitter();    //注册事件      event.on('some_event',function() {               console.log('这是一个自定义的js事件');      });      //触发事件    setTimeout(function(){        event.emit('some_event');    },3000);   `

2. NodeJs程序是由事件的循环开始,到事件的循环结束,所有的逻辑都在回调函数中处理;
3. 可以使用emit事件,触发事件;

第五讲: 模块和包


  1. 什么是模块;
    模块和文件是一一对应的.一个Node.js文件就是一个模块,这个文件可能是javascript代码,json或者编译过的C/C++扩展;
    var http = require(‘http’),其中http是node.js的一个核心的模块,通过reqire函数获取这个模块,然后使用其中的对象;
  2. 创建和加载模块;
    Node.js提供了exports和require两个对象,其中export是模块公开的接口,require用于从外部获取一个模块的接口,即获取模块的export对象;
    exports本身是一个普通的空对象,即{} ,它是专门用来声明接口的;
  3. 模块使用的一个小案例:

    `/*
    * @Author: Marte
    * @Date: 2017-04-15 12:48:28
    * @Last Modified by: Marte
    * @Last Modified time: 2017-04-15 12:54:04
    */

    // 需要导出的方法的类// 声明一个类function Hello(){    var name ;  //私有字段    this.setName = function(param){        name = param;    }; //方法    this.sayHello = function(){        console.log('Hello' + name);    }; //方法}//类定义接口,使得外部可以调用;module.exports = Hello;`

    `/*
    * @Author: Marte
    * @Date: 2017-04-15 12:54:52
    * @Last Modified by: Marte
    * @Last Modified time: 2017-04-15 12:58:11
    */

    //调用exportDemo中的js类中的方法var hello = require('./exoprtDemo');var he = new hello();he.setName('Peter');he.sayHello();var he2 = new hello();he2.setName('XCL');he2.sayHello();`

  4. 创建包;
  5. 包是模块基础上更深一步的抽象,类似于java net的类库,它将某个独立的功能封装起来,用于发布,更新,依赖管理的版本控制,开发了npm来解决包的发布和获取需求;
  6. 如何创建一个包:
    CommonJs规范的包应该是具备以下特征:

package.json必须在包的顶层目录下
二进制文件应该在bin目录下
JavaScript代码应该在lib目录下
文档应该在doc目录下
单元测试应该在test目录下
NodeJs对包要求并没有那么严格,只要顶层目录下有package.json,并符合基本规范即可;

7.package.json的规范

name: 包名,必须是唯一
description:包的简要说明
version:符合语义化版本识别规范的版本字符串
keywords: 关键词数据,通常用于搜索
maintainers: 包维护者,name ,email 可选字段
contributors:贡献者数组,格式月maintainers相同,第一个是作者
bugs: 提交bug的地址,可以是网址或者电子邮件地址;
repoistories: 仓库托管地址数组,每个元素要包含type,url和path字段信息
dependencies : 包的依赖,一个关联数组,由包的名称和版本号组成;

第六讲:包管理器和代码调试


  1. 如何使用包管理器
    Node.js包管理器,即npm是Node.js官方提供的包管理工具,已经成了node.js标准的发布平台,用户node.js包的发布,传播,依赖控制;
  2. 获取一个包;
    npm [install/i] [package_name]
  3. 卸载包 : npm uninstall [package_name] [-g]
  4. 查看包 npm list
  5. 本地模式和全局模式:
  6. npm 默认情况下,会从http://npmjs.org 搜索或者下载包,将包安装到当前node_modules
  7. a: 默认是npm install 包名 作为本地模式
    b: 全局模式 npm install -g 包名
    c: 区别和用法:
    因为本地模式不会注册PATH环境变量,npm本地模式仅仅是把包安装到了node_modules子目录下,其中bin目录没有包含在PATH环境变量中,不能直接在命令行中调用;

    使用全局模式安装的包并不能直接在JavaScript文件中require获得 因为require不会搜索/usr/local/lib/node_modules
    通俗讲:当我们要把某个作为项目运行时一部分时候,通过本地模式获取,如果是在命令行下使用,则使用全局模式;
    d: 包的发布:
    首先确保具备CommonJs为基础包的规范,但与CommonJs并不完全一致,其主要差别在与必填字段的不同,通过使用npm init 可以根据交互式问答产生一个符合标准的package.json
    dos进入要添加package.json的目录,npm init 得到执行的文件;在此目录下 npm publish完成发布包;

    如何更新包;在原来的包的基础上更新 npm publish
    如何取消 npm unpublish
    发布完成后在 http://search/npmjs.org/

第七讲: 全局对象和全局对象


概念:所有的属性都可以在程序的任何地方访问,即是全局变量。在JavaScript中,通常window是全局对象,而node.js的全局对象时global,所有的全局变量都是global对象的属性,如:console,process等等。
一:全局对象与全局变量
global最根本的作用是作为全局变量的宿主,满足一下条件成为全局变量;
1. 在最外层定义的变量;
2. 全局对象的属性;
3. 隐式定义的变量(未定义直接赋值的变量);
4. 在Node.js中不可能在最外层定义变量,因为素有的用户代码都是属于当前模块的,而模块本身不是最外层的上下文*

二: process
1. 它用于描述当前node.js进程对象,提供了一个与操作系统的简单接口,通常写本地命令行程序的时候,会用到他。
2. Process.argv 是命令行参数数组,第一个元素是node,第二个元素是脚本文件名,第三个元素开始是每个元素是一个运行参数。
3. Process.stdout是标准输出流,通常我们使用的console.log(),其底层是用Process.stdout.write();实现;
4. Process.stdin是标准的输入流,初始时候它是被暂停的。要想从 标准输入流读取数据,必须回复流,并手动编写流的事件响应的函数。
5. Process.nextTick(callback)的功能是为事件循环设置的一项任务。node.js会在下次事件循环调相应的callback,

Node.js适合IO密集型的应用,而不是计算密集型的应用,Process.nextTick()提供了一个这样的工具,可以把复杂的工作拆散,变成较小德尔事件;

Process其他方法:Process.platform(),process.pid(),process.execPath()等方法,参考连接
http://nodejs.org/api/process.html

`/* * @Author: Marte* @Date:   2017-04-16 22:37:52* @Last Modified by:   Marte* @Last Modified time: 2017-04-16 22:47:38*///使用process.nextTick使得程序执行速度加快,拆分成小程序//function compute(){    console.log('这是compute类中的方法');}function somethingComplited(args){    console.log('我是somethingComplited类中的方法');    console.log('我是我是somethingComplited类的传入的参数'+args)}//没用使用process.nextTick回调function doSomething(args,callback){    somethingComplited(args);    callback();}doSomething('123123',function onEnd(){    compute();});`

运行结果:

我是somethingComplited类中的方法
我是我是somethingComplited类的传入的参数123123
这是compute类中的方法

使用
` /*
* @Author: Marte
* @Date: 2017-04-16 22:37:52
* @Last Modified by: Marte
* @Last Modified time: 2017-04-16 22:54:31
*/
//使用process.nextTick使得程序执行速度加快,拆分成小程序
//

function compute(){    console.log('这是compute类中的方法');}function somethingComplited(args){    console.log('我是somethingComplited类中的方法');    console.log('我是我是somethingComplited类的传入的参数'+args)}//没用使用process.nextTick回调function doSomething(args,callback){    somethingComplited(args);     process.nextTick(callback)}doSomething('123123',function onEnd(){    compute();});`

运行结果,同上;

二: console

  1. console.log()向标准输出流打印字符并以换行符结束
  2. console.error()标准错苏流输出;
  3. console.trace()标准错误流输出单签的调用栈;

第八讲: 常用工具util


一,util 全局变量;
1. util.inherits(子类名,父类名)
此方法是一个实现对象间原型继承的函数,JavaScript通过原型赋值来实现继承;
原型继承父类中的方法,子类就可以调用父类中的方法,如下:
`/*
* @Author: Marte
* @Date: 2017-04-16 23:51:12
* @Last Modified by: Marte
* @Last Modified time: 2017-04-17 00:22:02
*/

        //演示 子类继承父类        var util = require('util');        //声明一个父类        function Base(){                //声明一个属性                this.name = 'base';                this.base = 2012 ;                //声明一个方法                this.sayHello = function(){                    console.log('我是父类Base中的声明的字段:' + this.name )                }        }        //在 类Base原型中赋值一个方法        Base.prototype.showName = function(){            console.log(this.name);        }        //声明一个子类        function Child(){            this.name = 'child';        }        //使用util子类继承父类;        util.inherits(Child,Base)        //实例一个父类,调用父类中的方法            var base = new Base();            base.showName();            base.sayHello();             console.log(base);//父类        //实例一个子类,尝试调用父类中的方法        var child = new Child();        child.showName();        //child.sayHello();//TypeError: child.sayHello is not a function  --所以这里是调用不了的        console.log(child); //子类

`

base
我是父类Base中的声明的字段:base
Base { name: ‘base’, base: 2012, sayHello: [Function] }
child
Child { name: ‘child’ }

  1. util.inspect(object,[showHidden],[depth],[colors])
    此方法是一个将任意对象转换为字符串的的方法,通常用于调试和错误输出,它至少接收一个参数Object。
    参数: Object ,要转换的对象;
    showHidden是一个可选的参数,如果是true,将会输出更多隐藏的信息;
    depth:标识最大的递归的层数,如果对象很复杂,可以指定输出的信息的多少,默认是2层,指定为null,打印出来全部;
    如果color为true,输出的格式将会一ANSI颜色编码,通常用于在终端显示更漂亮的效果;

    ` var util = require(‘util’);

    function Person(){    this.name = 'Peter';    this.toString = function(){        return this.name;    }}var obj = new Person();console.log(util.inspect(obj));console.log(util.inspect(obj,true,2,true));`

node执行结果:

Person { name: ‘Peter’, toString: [Function] }
Person {
name: ‘Peter’,
toString:
{ [Function]
[length]: 0,
[name]: ”,
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } } }

参考文档:http://nodejs.org/api

二、事件驱动events
events是node.js最重要的模板,原因是node.js本身架构就是事件式的,而且它提供了唯一的接口。node.js事件编程的基石,events模块不仅用于用户代码与node.js下层事件循环的交互,还几乎被所有的模块依赖;
1. 事件触发器:
events模块提供了一个对象。events.EventEmitter . EventEmitter的核心就是事件触发和事件监听功能的封装。EventEmitter的每个事件由一个事件或若干个参数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter支持若干个事件监听器。当事件触发是后,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递;
常用的api的方法介绍;
1. EventEmitter.on(event,listener)为指定事件注册一个监听器,接收一个字符串event和一个回调函数listener;
2. EventEmitter.emit(event,[arg1],[arg2]…)触发event事件,传递若干可选参数到事件监听器的参数表;
3. EventEmitter.once(event,listener)为指定事件注册一个单次监听器,即监听器最多只会触发一次,触发后立刻解除该监听器;
4. EventEmitter.removeListener(event,listener)移除指定事件的某个监听器。listener必须是该事件已经注册过的监听器;
5. EventEmitter.removeAllListeners([event])移除所有事件的所有监听器,如果指定event则移除指定事件的所有监听器;
2. error事件:
EventEmitter定义了一个特殊的事件error,它包含错误的定义,我们在遇到异常的时候,通常会触发error事件,当error事件触发时候,EventEmitter规定如果没有相应的监听器,node.js会把它当做异常,退出程序并打印调用栈,我们一般要为触发error的事件对象设置监听器,避免遇到错误后整个程序崩溃;

3. 继承EventEmitter
大多数时候我们不会直接使用EventEmitter,而是在对象中继承它,包括fs,net,http 在内的。只要是支持事件相应的核心模块的都是EventEmitter的子类;
目的:
1. 具有某个实体功能的对象实现,事件的监听和发射应该是一个对象的发放;
2. javascript的对象机制基于原型,支持部分剁成继承,继承EventEmitter不会打乱独享原有的继承关系 ;

事件案例:
`/*
* @Author: Marte
* @Date: 2017-04-17 23:25:48
* @Last Modified by: Marte
* @Last Modified time: 2017-04-17 23:47:02
*/

    //事件监听器      var events = require('events');    //实例化事件对象      var emitter = new events.EventEmitter();    //注册事件监听1    emitter.on('someEvent',function(arg1,arg2){        console.log('事件someEvent的监听事件1',arg1,arg2);    });    //注册事件监听2    emitter.on('someEvent', function(arg1,arg2) {       console.log('事件someEvent监听器2',arg1,arg2);    });    //触发事件    emitter.emit('someEvent','Peter',1991);`

运行结果:

事件someEvent的监听事件1 Peter 1991
事件someEvent监听器2 Peter 1991

第9讲:文件的操作


1.fs模块是文件操作的封装,它提供了文件的读取,写入,更名,删除,遍历目录,底层使用的是POSIX文件操作系统,与其他模块不同,fs模块中所有的操作都提供了异步和同步两个方法。例如 读取文件的内容,异步方法,readFile() ,同步方法readFileSync();
2.fs.readFileSync(fileName,[encoding])
同步读取文件,文件内容会以返回值的形式,返回,如果错误,fs将会抛出异常,需要try和catcha捕获并处理异常;
3. fs对象方法
参考api地址:
http://nodejs.org/api/fs.html

第10节:Http服务器

  1. Nodejs提供了http模块,其中封装了一个高效的http服务器和一简易的客户端;
  2. http.server是一个基于事件的http服务器,内部是C++实现,接口有JavaScript封装;
  3. http.request则是一个http客户端工具。用户向服务器发送请求;
    一、http服务器;

    1. http.Server实现,它提供了一套封装级别很低的api,仅仅是流控制和简单的解析,所有高层功能都需要他的接口;
    2. app.js文件:
    3. http.createServer创建了一个http.Server的实例,将一个函数作为http请求处理函数。这个函数接收两个参数,请求对象request和响应对象response, res显示的写入相应http的状态吗 200等,指定响应头,写入相应体。调用end结束并发送。该实例调用list函数,启动服务器并监听指定的端口号。如:3000端口。
    4. http.ServerRequest请求的信息:
      此对象是后端开发者最后在那关注的内容,它一般由http.Server的request事件发送,作为第一 个参数传递,通常简写成request或reg。http请求分为两部分,请求头和请求体。请求内容短的直接放在请求头解析完成后。立即读取,而请求体可能相对内容较长,需要一定的事件传输,因此共提供了三个事件用于控制请求体传输。
      (1)。 data:当请求体数据到来时,该事件被触发,该事件一共一个参数chunk,表示接受到的数据。
      (2)。 end:当请求数据传输完成时候,该事件被触发,此后,将不会再有数据到来。
      (3)。 close:用户当前请求结束是偶,该事件被触发,不同于end,如果用户轻质终止了传输,也为触发close事件。
      (4)。 complete:客户端请求是否已经发送完成。

      5.获取GET请求的内容信息;
      由于GEt气球直接被嵌入在路径中,url中?后边的解释get请求参数;Node.js的url模块中的parse函数提供了这个解析函数; 可以直接解析 get参数为对象;

      1. 获取post请求对象。
        post请求的内容都在请求体重,http.ServerRequest并没有一个属性内容为请求体,原因是等待请求体传输,可能是一件很耗时的工作,如上传文件,恶意的post请求会消耗服务器的资源,所有nodejs不会解析,请求体,需要的时候,需要手动的来解析;
  4. http.ServerResponse返回客户端对象;
    决定用户最终能的到的结果,
    它是由http.Server的request事件发送的,作为第二个参数传递,一般为response或res
    主要有三个函数;
    response.writeHead(statusCode,[headers])向请求的客户端发送响应头。
    statusCode,http状态码;
    header是一个类似数组的对象,表示响应头的每个属性。
    response.write(data,[encoding]).向请求的客户端发送响应的内容,data是buffer或者字符串encoding为编码,
    response.end([data],[encoding])结束响应,告知用用户所有发送已经完成,当所有返回的内容发送完毕,该函数必须被调用一次,如果不调用,客户端将永远处于等待状态;

    `/*
    * @Author: Marte
    * @Date: 2017-04-22 20:45:37
    * @Last Modified by: Marte
    * @Last Modified time: 2017-04-22 21:00:55
    */
    //监听,post请求,监听post请求内容,并将post字符串传转为对象,再将对象打印输出来;

    var http = require('http');var queryString = require('querystring');var util = require('util');http.createServer(function(requst,response){    var post ='';    //注册data事件监听函数,接收每次的请求体的数据,post请求请求的内容可能会很长的字符串    requst.on('data',  function(chunk) {        post += chunk;    });    //注册end事件,请求内容完毕,会触发end事件    requst.on('end', function() {    //解析post请求为对象    post=queryString.parse(post);    //向前端返回     response.end(util.inspect(post));    });}).listen(3000);console.log("服务器正在监听3000端口")

    `

Http客户端

一, http模块提供了两个函数http.request和http.get,功能是作为客户端想http服务器发起请求;
1.http.request(option,callback)发起http请求,option是一个类似关联数组的对象,表示请求的参数。callback是请求的回调函数,option常用的参数如下:
host:请求的域名或ip地址;
port:请求的端口号,默认是80;
method:请求方法,默认是get;
path:请求的根路径,默认是‘/’,QueryString,应该包含在其中,例如/search?name=xcl;
headers:请求头内容 ;
http.request返回一个http.clientRequest的实例;
二, http.get(option,callback)http模块还提供了一个更加简便的方法处理get请求,http.get它是http.request简化版版,唯一的区别是在http.get自动将请求方法设置get请求,同时不需要手动调用req.end();

三, http.ClientRequest。
该对象时有http.request或http.get返回的对象,表示一个已经产生的而且正在进行的http请求,它提供了Response事件,第二个参数指定的回调函数绑定对象,请求必须调用end方法结束请求。
提供函数:
request.abort()终止正在发送的请求,
request.setTimeOut(timeout,[callback])设置请求超时时间,timeout为毫秒数,请求超时后,会调用callback函数;
其他的request.setNoDelay([noDelay]),request.setScoketKeepAlive([enable],[initalDelay])等函数;

参考地址:http://nodejs.org/api/http.html

`/*
* @Author: Marte
* @Date: 2017-04-22 20:45:37
* @Last Modified by: Marte
* @Last Modified time: 2017-04-23 00:27:50
*/
//监听,get请求,演示http请求的流程

    var http = require('http');    var queryString = require('querystring');    //启动服务    http.createServer(function(requst,response){        console.log('客户端请求到来,解析参数')        var post ='';        //注册data事件监听函数,接收每次的请求体的数据,post请求请求的内容可能会很长的字符串        requst.on('data',  function(chunk) {            post += chunk;        });        //注册end事件,请求内容完毕,会触发end事件        requst.on('end', function() {            //解析post请求为对象            post=queryString.parse(post);            console.log('参数解析完成,返回post请求的name参数')            //向前端返回             console.log(post.name)            response.end(post.name);        });    }).listen(3000);    console.log("服务器正在监听3000端口")    //创建客户端请求    //1. 客户端请求体内容    var contents=queryString.stringify({        name:'xcl',        age:22,        address:'beijing'    });    //声明请求参数    var options ={        host:'localhost',        path:'/',        port:3000,        method:'post',        headers:{            'Content-Type':'application/x-www-form-urlencoded',            'Content-Length':contents.length        }    };    //发送请求    var req=http.request(options,function(res){        res.setEncoding('utf-8');        res.on('data',function(data){            console.log('后台接收了请求,并相应给客户端数据,返回数据为'+data)        })    });    //发送内容    req.write(contents);    //必须调用  request的end事件;     req.end();`   

执行结果:

服务器正在监听3000端口
客户端请求到来,解析参数
参数解析完成,返回post请求的name参数
xcl
后台接收了请求,并相应给客户端数据,返回数据为xcl

  1. http.get 演示
    `/*
    * @Author: Marte
    * @Date: 2017-04-23 00:37:10
    * @Last Modified by: Marte
    * @Last Modified time: 2017-04-23 00:50:39
    */
    //客户端的 http.get的介绍;

    var http = require('http');var util = require('util');var url = require('url');//启动服务http.createServer(function(request,response){    console.log('请求到来,开始解析请求参数');    var params = url.parse(request.url,true);    console.log('解析完成');    console.log(util.inspect(params));    console.log('向客户端返回数据');    response.end(params.query.name);}).listen(3000);//客户端请求http.get({    host:'localhost',    path:'/user?name=peter&age=12',    port:3000,},function(response){    response.setEncoding('utf-8');    response.on('data',function(data){         console.log('服务端响应数据为:'+ data);    });});`

执行结果:

请求到来,开始解析请求参数
解析完成
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: ‘?name=peter&age=12’,
query: { name: ‘peter’, age: ‘12’ },
pathname: ‘/user’,
path: ‘/user?name=peter&age=12’,
href: ‘/user?name=peter&age=12’ }
向客户端返回数据
服务端响应数据为:peter

0 0
原创粉丝点击