转载请注明出处:http://blog.csdn.net/gamer_gyt/
博主微博:http://weibo.com/234654758
Github:https://github.com/thinkgamer
写在前边的话
其实我个人对于接受新知识是有点抵触的,当然这里的新知识指的是除了大数据范畴之前的,就比如说nodejs,但是由于种种原因,我决定还是学习下吧,顺便在这个过程中把javascript也好好学习一番,至于我为什么抵触大数据之外的东西,是因为我觉得人应该有棱角,知识和技术也一样,如果你什么都会,但是什么都不精那就没意思了。
其实这一段时间一直有看elk的技术栈,在kibana的二次开发中,如果涉及到后台服务,那么nodejs就逃避不了了,当然还有难搞的js,反正我是很头疼。
Node.js是什么?
js是脚本语言,脚本语言都需要一个解析器才能运行。对于写在HTML页面里的JS,浏览器充当了解析器的角色。而对于需要独立运行的JS,NodeJS就是一个解析器。
每一种解析器都是一个运行环境,不但允许JS定义各种数据结构,进行各种计算,还允许js使用运行环境提供的内置对象和方法做一些事情。例如运行在浏览器中的js的用途是操作DOM,浏览器就提供了document之类的内置对象。而运行在Node.js中的JS的用途是操作磁盘文件或搭建HTTP服务器,Node.js就相应提供了fs、http等内置对象。
Node.js部署和简单使用
1:安装nvm
nvm是node.js版本管理工具,其全程是Node Version Manager,其实现是通过shell脚本,安装起来也比较方便
方法1:
curl https://raw.github.com/creationix/nvm/v0.4.0/install.sh | sh
方法2:
wget -qO- https://raw.github.com/creationix/nvm/v0.4.0/install.sh | sh
以上脚本会把nvm库clone到/.nvm,然后会在/.bash_profile, /.zshrc或/.profile末尾添加source,安装完成之后,你可以用nvm --help 来查看其使用方法
2:安装nodejs
目前node官网上得最新版本为7.6.0
安装:
nvm install v7.6.0
当然这里得版本号是你可以选择得,你也可以安装多个版本得node,然后通过nvm use 来选择你要使用得node版本,如果你不知道你现在使用得node版本,你可以通过以下命令来查看
$node -v
v7.6.0
3:npm介绍使用
npm是随同node.js一起安装得包管理工具,能解决Node.js代码部署上得很多问题,常用得使用场景有:
- 允许用户从NPM服务器上下载别人编写的第三方包到本地使用
- 允许用户从NPM服务器下载并安装别人编写得命令杭程序到本地使用
- 允许用户将自己编写的包或者命令程序上传到npm服务器供别人使用
由于新版得node.js已经集成了npm,在使用nvm install node-version之后, 可以使用npm -v来测试是否安装成功
$ npm -v
4.1.2
当然这里如果你使用的不是新版的npm,你可以使用下面的命令来升级npm
sudo npm install npm -g
npm install得时候有时候需要翻墙,这个时候就可以使用cnpm来替代npm,cnpm安装方式是:
npm install cnpm -g --registry=https://registry.npm.taobao.org
npm安装package分两种方式:本地安装和全局安装,区别是是否有 -g 标示,比如说:
npm install express //本地安装
npm install express -g //全局安装
其区别是:
- 本地安装将安装包放在./node_moudles下,如果没有该目录, 会生成一个目录。
- 全局安装是将安装包放在 /usr/local 下或者 你的node目录,你可以直接在命令行里调用。
你可以通过以下命令来查看你安装了那些全局包
npm ls -g
npm卸载,更新,搜索模块
npm uninstall express
npm update express
npm search express
npm 发布模块
(1):执行npm init ,按要求填写相应的信息,之后会在当前目录生成一个package.js的文件
(2):在npm 资源库中注册用户(使用邮箱注册)
$ npm adduser
Username:
Password:
Email: (this IS public) thinkgamer@163.com
(3):发布模块
npm publish
(4):如果你以上步骤都对,你就可以使用npm install 来安装你上传的模块
4:nodejs创建一个简单的项目
vim server.js,加入以下内容,然后执行node server.js
var http = require('http')
http.createServer(function (request, response){
response.writeHead(200,{'Content-Type': 'text/plain'});
response.end('Hello Thinkgamer,My blog is <a href="http://blog.csdn.net/gamer_gyt">Blog</a>\n')
}).listen(8888);
console.log('server as http://127.0.0.0.1:8888');
浏览器可看到:
分析代码:
第一行:引入node.js自带的http模块,并且赋值给http变量
接下来:调用createServer函数,返回一个对象,该对象有listen方法,指定服务器监听得端口号
5:Node.js REPL交互式解释器
通过node 进入
~$ node
常用的REPL命令:
ctrl + c - 退出当前终端。
ctrl + c 按下两次 - 退出 Node REPL。
ctrl + d - 退出 Node REPL.
向上/向下 键 - 查看输入的历史命令
tab 键 - 列出当前命令
.help - 列出使用命令
.break - 退出多行表达式
.clear - 退出多行表达式
.save filename - 保存当前的 Node REPL 会话到指定文件
.load filename - 载入当前 Node REPL 会话的文件内容。
Node.js的模块化
编写稍微大一点的程序时都会将代码模块化,在Nodejs中,一般将代码合理的拆分到不同的JS文件中,每一个文件就是一个模块,而文件路径就是模块名,在编写每个模块时,都有require,export,module三个预先定义好的变量可供使用。
1:require
require函数用于在当前模块中加载和使用别的模块,传入一个模块名,返回一个模块导出对象,模块名可使用相对路径(./开头),或者绝对路径(/ 或者C:之类的盘符开头),另外模块名中的.js扩展名可以省略。例如
var foo1 = require(’./hello’)
var foo2 = require(’./hello.js’)
两者保存的是同一个模块导出的对象
2:exports
exports是当前模块的导出对象,用于导出模块共有方法和属性,别的模块通过require函数使用当前模块时得到的就是当前模块的导出对象,例如test.js
exports.hello=function(){
console.log("hello, this is exports");
}
以上代码中,模块导出对象被替换为一个函数。
index.js内容如下:
var H = require('./test.js');
H.hello();
调用:
>node index.js
hello, this is exports
3:module
通过nodule对象可以访问到 当前模块的一些相关信息,但最多的用途是替换当前模块的导出对象。例如模块导出对象默认是一个普通对象,如果想改成一个函数的话,可以使用以下方式
test.js
module.exports=function(){
var name;
this.setName=function(new_name){
name=new_name;
};
this.showName=function(){
console.log(name);
};
}
当然这个地方还可以这样写(test.js):
function Hello(){
var name;
this.setName=function(new_name){
name=new_name;
};
this.showName=function(){
console.log(name);
};
};
module.exports=Hello;
index.js:
var Per = require('./test.js');
var p = new Per();
p.setName('thinkgamer');
p.showName();
调用:
>node index.js
thinkgamer
4:模块初始化
一个模块中的JS代码仅在模块第一次使用时执行一次,并在执行过程中初始化模块的导出对象,之后,缓存起来的导出对象被重复利用。
5:主模块
通过命令行参数传递给Nodejs以启动程序的模块被称为主模块,主模块负责调度组成整个程序的其他模块完成工作,例如通过以下命令来启动程序时,main.js就是主模块
$node main.js
Nodejs的代码组织
1:模块路径解析规则
(1) 内置模块
如果传递给require函数的是NodeJS内置模块名称,不做路径解析,直接返回内部模块的导出对象,例如require(‘fs’)。
(2) node_modules目录
NodeJS定义了一个特殊的node_modules目录用于存放模块。例如某个模块的绝对路径是/home/user/hello.js,在该模块中使用require(‘foo/bar’)方式加载模块时,则NodeJS依次尝试使用以下路径。
/home/user/node_modules/foo/bar
/home/node_modules/foo/bar
/node_modules/foo/bar
###(3)NODE_PATH环境变量
与PATH环境变量类似,NodeJS允许通过NODE_PATH环境变量来指定额外的模块搜索路径。NODE_PATH环境变量中包含一到多个目录路径,路径之间在Linux下使用:分隔,在Windows下使用;分隔。例如定义了以下NODE_PATH环境变量:
NODE_PATH=/home/user/lib:/home/lib
当使用require(‘foo/bar’)的方式加载模块时,则NodeJS依次尝试以下路径。
/home/user/lib/foo/bar
/home/lib/foo/bar
2:包(package)
我们知道js模块的基本文件是单个js文件,但复杂些的模块往往由多个子模块组成,为了便于管理和使用,我们把由多个子模块组成的大模块称作包,并把所有子模块放在同一个目录下。
在组成一个包的所有子模块中,需要有一个入口模块,入口模块的导出对象被作为包的导出对象。例如有以下目录结构。
- /home/user/lib/
- cat/
head.js
body.js
main.js
其中cat目录定义了一个包,其中包含了3个子模块。main.js作为入口模块,其内容如下:
var head = require('./head');
var body = require('./body');
exports.create = function (name) {
return {
name: name,
head: head.create(),
body: body.create()
};
};
在其它模块里使用包的时候,需要加载包的入口模块。接着上例,使用require(’/home/user/lib/cat/main’)能达到目的,但是入口模块名称出现在路径里看上去不是个好主意。因此我们需要做点额外的工作,让包使用起来更像是单个模块。
index.js
当模块的文件名是index.js,加载模块时可以使用模块所在目录的路径代替模块文件路径,因此接着上例,以下两条语句等价。
var cat = require(’/home/user/lib/cat’);
var cat = require(’/home/user/lib/cat/index’);
这样处理后,就只需要把包目录路径传递给require函数,感觉上整个目录被当作单个模块使用,更有整体感。
package.json
如果想自定义入口模块的文件名和存放位置,就需要在包目录下包含一个package.json文件,并在其中指定入口模块的路径。上例中的cat模块可以重构如下。
- /home/user/lib/
- cat/
+ doc/
- lib/
head.js
body.js
main.js
+ tests/
package.json
其中package.json内容如下。
{
"name": "cat",
"main": "./lib/main.js"
}
如此一来,就同样可以使用require(’/home/user/lib/cat’)的方式加载模块。NodeJS会根据包目录下的package.json找到入口模块所在位置。
3:工程目录
以编写一个命令行程序为例,一般我们会同时提供命令行模式和API模式两种使用方式,并且我们会借助三方包来编写代码。除了代码外,一个完整的程序也应该有自己的文档和测试用例。因此,一个标准的工程目录都看起来像下边这样。
- /home/user/workspace/node-echo/ # 工程目录
- bin/ # 存放命令行相关代码
node-echo
+ doc/ # 存放文档
- lib/ # 存放API相关代码
echo.js
- node_modules/ # 存放三方包
+ argv/
+ tests/ # 存放测试用例
package.json # 元数据文件
README.md # 说明文件
其中部分文件内容如下:
/* bin/node-echo */
var argv = require('argv'),
echo = require('../lib/echo');
console.log(echo(argv.join(' ')));
/* lib/echo.js */
module.exports = function (message) {
return message;
};
/* package.json */
{
"name": "node-echo",
"main": "./lib/echo.js"
}
以上例子中分类存放了不同类型的文件,并通过node_moudles目录直接使用三方包名加载模块。此外,定义了package.json之后,node-echo目录也可被当作一个包来使用。
下一篇: Node.js历险记之express框架入门篇
扫一扫 关注微信公众号!号主 专注于搜索和推荐系统,尝试使用算法去更好的服务于用户,包括但不局限于机器学习,深度学习,强化学习,自然语言理解,知识图谱,还不定时分享技术,资料,思考等文章!