【菜鸟教程学习笔记】Node.js入门学习

前言

本系列为学习笔记。
是从菜鸟教程上学的。

NodeJS

简单的说 NodeJS就是运行在服务器端的JavaScript。
Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。
Node.js是一个事件驱动的I/O服务端JavaScript环境,基于Goole的V8引擎,V8引擎执行JavaScript的速度非常快,性能非常好。

安装配置

本安装教程已Node.js v4.4.3 LTS 版本为例
Node.js安装包及源码下载地址为:https://nodejs.org/en/download/

你可以根据自不同的平台选你需要的Node.js安装包。
注:Linux 上安装Node.js 需要安装Python 2.6或2.7,不建议安装Python 3.0 以上版本

Window 上安装Node.js

有两种安装方式:

  1. Windows 安装包(.msi)
    一直点下一步就好了,将node加入环境变量,安装的时候它好像是默认不添加的,如果不想自己手动添加的话,建议勾选一下Add to PATH。
    安装后检测PATH 环境变量是否配置了Node.js,点击开始=》运行=》输入cmd =》输入path
    就会输出所有已配置的path
    如果node已添加到环境变量中使用 node --version 可以检查Node.js版本。

  2. Windows二进制文件(.exe)安装
    依然是一连串的下一步。

Ubuntu 上安装Node.js

源码安装

以下将介绍在Ubuntu Linux 下安装Node.js。其他的Linux系统,如Centos 等类似如下安装步骤:
在GitHub上获取Node.js 源码:

$ sudo git clone https://github.com/nodejs/node.git
Cloning into 'node' ...

修改目录权限:
$ sudo chmod -R 755 node
使用./configure 创建编译文件,并按照:

$ cd node
$ sudo ./configure
$ sudo make
$ sudo make install

Ubunto apt-get命令安装
命令格式如下:

sudo apt-get install nodejs
sudo apt-get install npm

CentOS 下安装NOde.js

  1. 下载源码
cd /usr/local/src/
wget  源码URL
  1. 解压源码
tar zxvf 安装包名
  1. 编译安装
cd node-v0.10.24
./configure --prefix=/usr/local/node/0.10.24
make make install
  1. 配置NODE_HOME ,进入profile 编辑环境变量
vim /etc/profile

设置nodejs环境变量,在 export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL 一行的上面添加如下内容:

#set for nodejs
export NODE_HOME=/usr/local/node/0.10.24
export PATH=$NODE_HOME/bin:$PATH

:wq保存并退出,编译/ect/profile 使配置生效。
source /ect/profile
验证是否安装配置成功

node -v

注:Nodejs 官网提供了编译好的Linux 二进制包,你也可以下载下来直接应用。

创建第一个应用

如果我们使用PHP来编写后端的代码时,需要Apache 或者Nginx 的HTTP 服务器,并配上 mod_php5 模块和 php_cgi。
从这个角度看,整个“接收HTTP请求并提供Web页面”的需求根本不需要PHP来处理。
不过,对Node.js来说,概念完全不一样了。使用Node.js时,我们不仅仅在实现一个应用,同时还实现了整个HTTP服务器。
事实上,我们的web应用及对应的web服务器基本上是一样的。
在我们创建Node.js 第一个“hello,world!”应用之前,让我们先了解一下Node.js 应用是由哪几部分组成的:

  1. 引入 http 模块:我们可以使用require 指令来载入Node.js 模块
  2. 创建服务器:服务器可以监听客户端的请求,类似于Apache、Nginx等http服务器。
  3. 接收请求与响应请求。服务器很容易创建,客户端可以使用浏览器或终端发送http请求,服务器接收请求后返回响应数据。

创建Node.js 应用

步骤一 引入http 模块

我们使用 require 指令来载入http 模块,并将实例化的http赋值给变量http,实例如下:

var http = require("http");

步骤二 创建服务器

接下来我们使用 http.createServer() 方法创建服务器,并使用listen 方法绑定 8888 端口。函数通过request,response 参数来接收和响应数据。
实例如下,在项目根目录下创建 server.js 文件,并写入一下代码:

var http = require('http');
http.createSerer(function(request,response){
    //发送HTTP头部
    // HTTP 状态值 : 200 OK
    //内容类型:text/plain
    response.writeHead(200,{"Content-Type":"text/plain"});
    // 发送响应数据 “hello,world!”
    response.end("Hello World\n");
}).listen(8888);
// 终端打印如下信息
console.log("Server running at http://127.0.0.1:8888/");

以上代码我们完成了一个可以工作的http服务器。
使用node 命令执行以上的代码:

node server.js
Server running at http://127.0.0.1:8888/

接下来,打开浏览器访问http://127.0.0.1:8888/ ,你会看到一个写着“hello world”的网页。

分析Node.js 的HTTP服务器:

  • 第一行请求(require)Node.js 自带的http 模块,并且把他赋值给http 变量。
  • 接下来我们调用http 模块提供的函数:createServer 。这个函数会返回一个对象,这个对象有一个叫做listen 的方法,这个方法有一个数值参数,指定这个HTTP服务器监听的端口号。
    实例演示
    image.png

npm使用介绍

这里只简单介绍npm的使用,详细的内容可以访问npm中文网的文档,写的也挺详细的https://www.npmjs.com.cn/


NPM 是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有如下几种:

  • 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
  • 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
  • 允许用户将自己编写的包或命令程序上传到NPM服务器供别人使用。

新版的nodejs 已经集成了npm,我们可以通过输入"npm -v"来测试是否成功安装。出现版本提示表示安装成功。

如果你安装的是旧版本的npm , 可以很容易地通过 npm 命令来升级,命令如下:

$ sudo npm install npm -g
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
npm@2.14.2 /usr/local/lib/node_modules/npm

如果是Windows 系统使用以下命令即可:

npm install npm -g

使用npm 命令安装模块

npm 安装 Node.js 模块语法格式如下:

$ npm install <Module Name>

以下实例,我们使用 npm 命令安装常用的Node.js web框架模块 express :

$ npm install express

安装好之后,express就放在了工程目录下的node_modules 目录中,因此在代码中只需要通过require('express') 的方式就好,无需指定第三方包路径。

var express = require("express");

全局安装与本地安装

npm 的包安装分为本地安装(local)、全局安装(global)两种,从敲的命令来看,差别只是有没有-g而已,比如:

npm install express     #本地安装
npm install express -g #全局安装

如果出现以下错误:

npm err! Error: connect ECONNREFUSED 127.0.0.1:8087

解决方法为:

$ npm config set proxy null

本地安装

  1. 将安装包放在 ./node_modules下(运行npm命令时所在的目录),如果没有node_modules 目录,会在当前执行npm 命令的目录下生成node_modules 目录。
  2. 可以通过require() 来引入本地安装包。

全局安装

  1. 将安装包放在 /usr/local 下或者你 node 的安装目录
  2. 可以直接在命令行里使用
    如果你希望具备两者功能,则需要在两个地方安装它或者使用 npm link
    接下来我们使用全局安装express
$ npm install express -g

安装过程输出内容,第一行输出了模块的版本号及安装位置。

查看安装信息

你可以使用以下命令来查看所有全局安装的模块:

$ npm list -g

如果要查看某个模块的版本号,可以使用命令如下:

$ npm list <Module name>

使用 package.json

package.json 位于模块的目录下,用于定义包的属性。接下来看下 express 包的 package.json 文件,位于 node_modules/express/package.json 内容:

Package.json 属性说明

  • name 包名
  • version 包的版本号
  • description 包的描述
  • homepage 包的官网URL
  • author 包的作者姓名
  • contributors 包的其他贡献者姓名
  • dependencies 依赖包列表。如果依赖包没有安装,npm会自动将依赖包安装在 node_modules目录下。
  • repository 包代码存放放的地方的类型,可以是git 或svn,git可在GitHub上。
  • main 指定了程序的主入口文件,require(‘moduleName’)就会加载这个文件。这个字段默认值是模块跟目录下面的 index.js
  • keywords 关键字

卸载模块

$ npm uninstall express

更新模块

$ npm update express

创建模块

创建模块,package.json 文件是必不可少的。我们可以使用npm 生成package.json文件,生成的文件包含了基本的结果。

$ npm init

接下来我们可以使用以下命令在npm资源库中注册用户(使用邮箱注册):

$ npm add user
Username : mcmohd
Password:
Email : (this IS public) mcmohd@mail.com

接下来我们就用以下命令来发布模块:

$ npm publish

如果你以上步骤都操作正确,你就可以跟其他模块一样使用npm来安装。

版本号

使用NPM下载和发布代码时都会接触到版本号。NPM 使用语义版本号来管理代码,这里简单介绍以下。
语义版本号分为X.Y.Z三位,分别代表主版本号、次版本号和补丁版本号。当代码变更时,版本号按以下原则更新。

  • 如果只是修复bug,需要更新Z位
  • 如果是新增了功能,但是向下兼容,需要更新Y位。
  • 如果有大变动,向下不兼容,需要更新X位。
    版本号有了保证后,在申明第三方包依赖时,除了可依赖于一个固定版本号外,还可依赖于某个范围的版本号。
    例如"argv":"0.0.x"表示依赖于0.0.x系列的最新版argv。
    npm支持的所有版本号范围指定方式可以查看官方文档。

NPM常用命令

除了本章介绍的部分外,NPM还提供了很多功能,package.json里也有很多其他有用的字段。
在npmjs可查看官方文档,这里再介绍一些NPM常用命令:

  • 使用 npm help 可查看所有命令。
  • 使用 npm help <command> 可查看某条命令的详情帮助,例如 npm help install
  • 在package.json 所在目录下使用npm install . -g 可在本地安装当前命令行程序,可用于发布前的本地测试。
  • 使用 npm update <package> 可以把当前目录下node_modules子目录里的对应模块更新至最新版。
  • 使用 npm update <package> -g 可以把全局安装的对应命令行程序更新至最新版
  • 使用 npm cache clear 可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人
  • 使用 npm unpublish <package>@<version> 可以撤销发布自己发布过的某个版本代码

使用淘宝镜像

大家都知道国内镜像使用npm 的官方镜像是非常慢的,这里推荐使用淘宝NPM镜像。
淘宝NPM镜像是一个完整npmjs.org镜像,你可以用此代替官方版本(只读),同步频率目前为10分钟一次以保证尽量与官方同步。
你可以使用淘宝定制的cnpm(gzip压缩支持)命令行工具代替默认的npm :

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

这样就可以使用cnpm 命令来安装模块了:

$ cnpm install [name]

更多信息可以查阅:http://npm.taobao.org

本章总结:

  1. npm 的常用使用场景
  2. npm 的升级
  3. 使用 npm 命令安装模块
  4. 全局安装与本地安装
  5. 查看安装信息
  6. 使用package.json及package.json 属性说明
  7. 卸载模块
  8. 更新模块
  9. 搜索模块
  10. 创建模块
  11. 注册npm库用户
  12. 发布模块
  13. 版本号介绍
  14. NPM常用命令
  15. 使用淘宝镜像

REPL

什么是REPL

REPL : Read Eval Print Loop : 交互式解释器。表示电脑的一个环境,类似Windows 系统的终端或Unix/Linux shell,我们可以在终端中输入命令,并接收系统的响应。

Node 自带了交互式解释器,可以执行以下任务:

  • 读取 - 读取用户输入,解析输入的JavaScript 数据结构并存储在内存中
  • 执行 - 执行输入的数据结构
  • 打印 - 输出结果
  • 循环 - 循环操作以上步骤直到用户两次按下 Ctrl - c 按钮退出

Node 的交互解释器可以很好的调试JavaScript代码。

开始学习 REPL

我们可以输入以下命令来启动Node 的终端;

$ node
>

这时我们就可以在> 后输入简单的表达式,并按下回车键来运算结果。

简单的表达式运算

接下来我们在Node.js REPL 的命令窗口中执行简单的数学运算:

$ node
> 1 +4
5
> 5 / 2
2.5
> 3 * 6
18
> 4 - 1
3
> 1 + ( 2 * 3 ) - 4
3
>

使用变量

你可以将数据存储在变量中,并在你需要的时候使用它。
变量声明需要使用var 关键字,如果没有使用var 关键字,变量会直接打印出来。
使用var 关键字的变量可以使用 console.log() 来输出变量。

$ node
> x = 10
10
> var y = 10
undefined
> x + y
20
> console.log("Hello World")
Hello World
undefined
> console.log("www.runoob.com")
www.runoob.com
undefined

多行表达式

Node REPL 支持输入多行表达式,这就有点类似JavaScript。接下来我们执行一个do-while 循环:

$ node
> var x = 0
undefined
> do {
... x++;
... console.log("x: " + x);
... } while ( x < 5 );
x: 1
x: 2
x: 3
x: 4
x: 5
undefined
>

...三个点的符号是系统自动生成的,你回车换行后即可。Node 会自动检测是否为连续的表达式。

下划线(_)变量

你可以使用下划线(_)获取上一个表达式的运算结果:

> var x=10
undefined
> var y=10
undefined
> x+y
20
> var sum=_
undefined
> sum
20
>

REPL 命令

  • Ctrl + c : 退出当前终端
  • Ctrl + c 两次 : 退出Node REPL
  • Ctrl + d : 退出Node REPL
  • 向上、向下键 : 查看输入的历史命令
  • tab键 : 列出当前命令
  • .help : 列出使用命令
  • .break : 退出多行表达式
  • .clear : 退出多行表达式
  • .save filename : 保存当前的REPL 会话到指定文件
  • .load filename : 载入当前Node REPL 会话的文件内容

停止REPL

前面我们已经提到按两下 Ctrl+c 键就能退出REPL。

回调函数

Node.js 异步编程的直接体现就是回调。
异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。
回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有API 都支持回调函数。
例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。
回调函数一般作为最后一个参数出现:

function foo1(name, age, callback) { }
function foo2(value, callback1, callback2) { }

阻塞代码示例

创建一个文件 input.txt ,内容如下:

我多想成为一颗星

另一个我与我平行

每一次梦中的愿景

在一颗星上实现

仰望星空,偌大的时空

畅想着多重可能

泪水蒸发在悲伤

欢愉流淌于溪水

彼此交融在思想

交换了场景,在不同的星上

我坐落在一颗星上

在色彩斑斓的世界里遥望

当光明沉睡

寄送来的一颗星

是属于我的平行

作者:不俗小七
链接:https://www.jianshu.com/p/5bea3b0cb154
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

创建 main.js 文件,代码如下:

var fs = require("fs")
var data = fs.readFileSync("input.txt");
console.log(data.toString());
console.log("程序执行结束!")

以上代码执行结果如下:

D:\WorkStudy\StudySpace\Nodejs\runoob>node main.js
我多想成为一颗星

另一个我与我平行

每一次梦中的愿景

在一颗星上实现

仰望星空,偌大的时空

畅想着多重可能

泪水蒸发在悲伤

欢愉流淌于溪水

彼此交融在思想

交换了场景,在不同的星上

我坐落在一颗星上

在色彩斑斓的世界里遥望

当光明沉睡

寄送来的一颗星

是属于我的平行

作者:不俗小七
链接:https://www.jianshu.com/p/5bea3b0cb154
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
程序执行结束!

D:\WorkStudy\StudySpace\Nodejs\runoob>

非阻塞代码实例

依然使用上面创建的input.txt 文件。

创建 main2.js 文件,代码如下:

var fs = require("fs");

fs.readFile('input.txt', function (err, data) {
    if (err) return console.error(err);
    console.log(data.toString());
});

console.log("程序执行结束!");

以上代码执行结果如下:

D:\WorkStudy\StudySpace\Nodejs\runoob>node main.js
我多想成为一颗星

另一个我与我平行

每一次梦中的愿景

在一颗星上实现

仰望星空,偌大的时空

畅想着多重可能

泪水蒸发在悲伤

欢愉流淌于溪水

彼此交融在思想

交换了场景,在不同的星上

我坐落在一颗星上

在色彩斑斓的世界里遥望

当光明沉睡

寄送来的一颗星

是属于我的平行

作者:不俗小七
链接:https://www.jianshu.com/p/5bea3b0cb154
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
程序执行结束!

D:\WorkStudy\StudySpace\Nodejs\runoob>

以上两个实例我们了解了阻塞与非阻塞调用的不同。第一个实例在文件读取完后才执行完程序。第二个实例我们不需要等待文件读取完,这样就可以在读取文件时同时执行接下来的代码,大大提高了程序的性能。
因此,阻塞时按顺序执行的,而非阻塞时不需要按顺序的,所以如果需要处理回调函数的参数,我们就要写在回调函数内。

回调疑惑

不过我这里有个问题用非阻塞方式时,当我在读文件的时候同时在执行其他的代码,但是这段代码执行到一个地方需要用到读取文件后的结果,这时,我该怎么办了呢?把外面这段代码写到回调函数里面去吗?这样的话,我外面的代码就相当于在回调中阻塞了。有什么解决方案吗?

事件循环

Node.js 事件循环

Node.js 是单进程单线程应用程序,但是因为V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
Node.js 几乎每一个API 都是支持回调函数的。
Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现。
Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数。

事件驱动程序

Node.js 使用事件驱动模型,当web server接收到请求,就把它关闭然后进行处理,然后去服务下一个web请求。
当这个请求完成,它被放回处理队列,当到达队列开头,这个结果被返回给用户。
这个模型非常高效可扩展性非常强,因为webserver 一直接受请求而不等待任何读写操作。(这也被称之为非阻塞式IO或者时间驱动IO)
在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。


image.png

整个事件驱动的流程就是这么实现的,非常简洁。有点类似于观察者模式,事件相当于一个主题(Subject),而所有注册到这个事件上的处理函数相当于观察者(Observer)。
Node.js 有多个内置的事件,我们可以通过引入events 模块,并通过实例化 EventEmitter 类来绑定和监听事件,如下实例:

// 引入 events 模块
var events = require("events");
// 创建eventEmitter 对象
var eventEmitter = new events.EventEmitter();

绑定事件处理程序:

eventEmitter.on("eventName",eventHandler);

触发事件:

eventEmitter.emit("eventName");
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容