Node.js学习

学习教程

一、node.js特征
  • Node.js 异步编程的直接体现就是回调。
  • Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
二、npm常用命令
  • npm help 查看所有命令
  • npm help 可查看某条命令的详细帮助,例如npm help install。
  • 在package.json所在目录下使用npm install . -g可先在本地安装当前命令行程序,可用于发布前的本地测试。
  • 使用npm update 可以把当前目录下node_modules子目录里边的对应模块更新至最新版本。
  • 使用npm update -g可以把全局安装的对应命令行程序更新至最新版。
  • 使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人。
  • 使用npm unpublish @可以撤销发布自己发布过的某个版本代码。
三、命令
  • 项目终端输入node --version 查看版本,如果没版本号就是没安装
    在这里插入图片描述
  • npm -v 查看npm版本
四、使用npm命令安装模块
  • npm install express ; npm install express -g 全局安装

npm 命令安装常用的 Node.js web框架模块 express:
安装好之后,express 包就放在了工程目录下的 node_modules 目录中,因此在代码中只需要通过 require(‘express’) 的方式就好,无需指定第三方包路径。

使用:var express = require('express');

  • 使用npm卸载模块
    npm uninstall express
  • 使用npm更新模块
    npm update express
  • 使用npm搜索模块
    npm search express
  • 终端输入 node xxx.js 启动该文件
八、package.json

package.json 位于模块的目录下,用于定义包的属性

// Package.json 属性说明
name - 包名。
version - 包的版本号。
description - 包的描述。
hompage - 包的官网 url 。
author - 包的作者姓名。
contributors - 包的其他贡献者姓名。
dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。
repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。
main - main 字段指定了程序的主入口文件,require('moduleName') 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。
keywords - 关键字
九、创建模块

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

  • npm init
Press ^C at any time to quit.
name: (node_modules) runoob                   # 模块名
version: (1.0.0) 
description: Node.js 测试模块(www.runoob.com)  # 描述
entry point: (index.js) 
test command: make test
git repository: https://github.com/runoob/runoob.git  # Github 地址
keywords: 
author: 
license: (ISC) 
About to write to ……/node_modules/package.json:      # 生成地址

{
  "name": "runoob",
  "version": "1.0.0",
  "description": "Node.js 测试模块(www.runoob.com)",
  ……
}


Is this ok? (yes) yes

以上的信息,你需要根据你自己的情况输入。在最后输入 “yes” 后会生成 package.json 文件。

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

$ npm adduser
Username: mcmohd
Password:
Email: (this IS public) [email protected]

接下来我们就用以下命令来发布模块:
$ npm publish
通过以上步骤我们自己创建的模块就可以跟其他模块一样使用 npm 来安装。

十、使用淘宝npm镜像

由于国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像。

淘宝 NPM 镜像是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。

你可以使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:

$ npm install -g cnpm --registry=https://registry.npmmirror.com

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

$ cnpm install [name]

更多信息可以查阅:https://npmmirror.com/。

nodejs

  • node.js应用由哪几部分组成
    1.引入required模块:我们可以使用 require 指令来载入 Node.js 模块。
    2.创建服务器:服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。
    3.接收请求与响应请求 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。
十一、Node.js REPL(交互式解释器)

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

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

读取 - 读取用户输入,解析输入的 Javascript 数据结构并存储在内存中。

执行 - 执行输入的数据结构

打印 - 输出结果

循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。

  • 启动Node的终端
    在项目终端输入 node来启动node终端,通过回车来计算结果
    在这里插入图片描述
  • 简单的表达式运算
PS D:\work\lx\nodejs> node
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> 1 +4
5
> 5/2
2.5
> 3*6
18
> 1 + (2*3)-4
3
>

  • 使用变量

你可以将数据存储在变量中,并在你需要的时候使用它。

变量声明需要使用 var 关键字,如果没有使用 var 关键字变量会直接打印出来。

使用 var 关键字的变量可以使用 console.log() 来输出变量。

PS D:\work\lx\nodejs> node
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> x=10
10
> var y=10
undefined
> x+y
20
> console.log("hello")
hello
undefined
>
  • 多行表达式

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

> 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
> y = 30
30
> x+y
40
> var sum = _
undefined
> console.log(sum)
40
undefined
>
  • 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 回调函数

Node.js 异步编程的直接体现就是回调。

异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。

回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。

例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件
I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。

回调函数一般作为函数的最后一个参数出现:

function foo1(name, age, callback) { }
function foo2(value, callback1, callback2) { }
  • 阻塞案例
var fs = require("fs");

var data = fs.readFileSync('input.txt');//Sync同步;执行完当前操作才能进行下一个操作
console.log(data.toString());
console.log('程序执行结束!');

-----------------
//执行结果
PS D:\work\lx\nodejs> node main.js
hello world nodejs;
程序执行结束!
  • 非阻塞案例
var fs = require('fs');

fs.readFile('input.txt',function(err,data){//异步: 此操作的执行结不结束不影响后面其他代码执行
    if(err) return console.log(err);
    console.log(data.toString());
});

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

-----------------
//执行结果
PS D:\work\lx\nodejs> node main2.js
程序执行结束!
hello world nodejs;

以上两个实例我们了解了阻塞与非阻塞调用的不同。第一个实例在文件读取完后才执行程序。
第二个实例我们不需要等待文件读取完,这样就可以在读取文件时同时执行接下来的代码,大大提高了程序的性能。

因此,阻塞是按顺序执行的,而非阻塞是不需要按顺序的,所以如果需要处理回调函数的参数,我们就需要写在回调函数内

十三、事件驱动 程序

Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件

  • event emitters 事件发射器
  • event handlers 事件处理程序
 // 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();

以下程序绑定事件处理程序:

// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);

我们可以通过程序触发事件:

// 触发事件
eventEmitter.emit('eventName');
  • 实例
// 引入 event模块
var events = require('events');
//创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();

//创建事件处理程序
var connectHandler = function connected(){
    console.log('连接成功');

    //触发 data_received 事件
    eventEmitter.emit('data_received');
}
//绑定 connection事件处理程序
eventEmitter.on('connection',connectHandler);

//使用匿名函数绑定data_received 事件
eventEmitter.on('data_received',function(){
    console.log('数据接收成功')
})

//触发 connection 事件
eventEmitter.emit('connection');

console.log('程序执行完毕');
十四、Node.js Buffer(缓冲区)

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型,但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

十五、Node.js模块系统

为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。
模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。

  • 创建模块
exports.world = function() {
  console.log('Hello World');
}
  • 引入模块
var hello = require('./hello');/// 为当前目录,node.js 默认后缀为 js
hello.world();

Node.js 提供了 exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。

node.js 默认后缀为 js

  • 有时候我们想把一个对象封装到模块里
module.exports = function() {
  // ...
}

例子

//hello.js 
function Hello() { 
    var name; 
    this.setName = function(thyName) { 
        name = thyName; 
    }; 
    this.sayHello = function() { 
        console.log('Hello ' + name); 
    }; 
}; 
module.exports = Hello;
//main.js 
var Hello = require('./hello'); 
hello = new Hello(); 
hello.setName('BYVoid'); 
hello.sayHello(); 

exports 和 module.exports 的使用 如果要对外暴露属性或方法,就用 exports就行,要暴露对象(类似class,包含了很多属性和方法),就用 module.exports。

不建议同时使用 exports 和 module.exports。

如果先使用 exports 对外暴露属性或方法,再使用 module.exports 暴露对象,会使得 exports
上暴露的属性或者方法失效。

原因在于,exports 仅仅是 module.exports 的一个引用。

function require(...){
  var module = {exports: {}};

  ((module, exports) => {
    function myfn () {}
    // 这个myfn就是我们自己的代码
    exports.myfn = myfn; // 这里是在原本的对象上添加了一个myfn方法。
    module.exports = myfn;// 这个直接把当初的对象进行覆盖。
  })(module,module.exports)
  return module.exports;
}
  • require方法接受以下几种参数的传递:

1.http、fs、path等,原生模块。
2. ./mod或…/mod,相对路径的文件模块。
3. /pathtomodule/mod,绝对路径的文件模块。
4.mod,非原生模块的文件模块。

十六、路由

parse 解析
query 查询

全局变量

Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。
当你定义一个全局变量时,这个变量同时也会成为全局对象的属性,反之亦然。需要注 意的是,在 Node.js 中你不可能在最外层定义变量,因为所有用户代码都是属于当前模块的, 而模块本身不是最外层上下文。
注意: 最好不要使用 var 定义变量以避免引入全局变量,因为全局变量会污染命名空间,提高代码的耦合风险。

  • __filename
    表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径。
// 输出全局变量 __filename 的值
console.log( __filename );
  • __dirname
    __dirname 表示当前执行脚本所在的目录。
常用工具
  • util
    util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心 JavaScript 的功能 过于精简的不足。
文件系统模块 fs

Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
建议大家使用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。
-fs 方法

/**
 * 1打开文件
 * 以下是在异步模式下打开文件语法格式
 * fs.open(path,flags[,mode],callback)
 * 参数
 * path:文件路径
 * flags:文件打开的行为
 * mode:设置文件模式(权限),文件创建默认权限为0666(可读,可写)
 * callback-回调函数,带有两个参数如:callback(err,fd)
 */

var fs  = require('fs');

// 异步打开文件
console.log('准备打开文件');
fs.open('input.txt','r+',function(err,fd){
    if(err){
        return console.error(err);
    }
    console.log('文件打开成功!');
})

/**
 * 2获取文件信息
 * fs.stat(path,callback)
 * 参数:
 * callback:两个,err,stats,stats是fs.State的对象
 * fs.stat(path)执行后,会将stats类的实例返回给其回调函数。可以通过stats类中的提供方法判断文件的相关属性。例如判断是否为文件:
 * 
 * isFile是文件
 * isDirectory是否是目录
 * isBlockDevice是块设备
 * isCharacterDevice是字符设备
 * isSymbolicLink是软链接
 * isFIFO是FIFO
 * isSocket是 Socket 返回 true
 */

fs.stat('input.txt',function(err,stats){
    console.log(stats.isFile(),'是否是文件');
})

/**
 * 3写入文件
 * fs.writeFile(file, data[, options], callback)
 * 
 * writeFile 直接打开文件默认是 w 模式,所以如果文件存在,该方法写入的内容会覆盖旧的文件内容!!!
 * 参数
 * file文件名或文件描述符
 * data:要写入文件的数据,可以是string或buffer(缓冲对象
 * options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 'w'
 * callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。
 */

console.log('准备写入文件')
fs.writeFile('input.txt','我是通过 fs.writeFile写入文件内容的',function(err){
    if(err){
        return console.error(err)
    }
    console.log('数据写入成功!')
    console.log('---我是分界线---')
    console.log('读取刚刚写入的新数据!')
    fs.readFile('input.txt',function(err,data){
        if(err){
            return console.error(err);
        }
        console.log('异步读取文件数据:',data.toString())
    })
})


/**
 *4 异步读取文件
 * fs.read(fd, buffer, offset, length, position, callback)
 * fd - 通过 fs.open() 方法返回的文件描述符。
参数:
buffer - 数据写入的缓冲区。
offset - 缓冲区写入的写入偏移量。
length - 要从文件中读取的字节数。
position - 文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。
callback - 回调函数,有三个参数err, bytesRead, buffer,err 为错误信息, bytesRead 表示读取的字节数,buffer 为缓冲区对象。
 */

var buf = new Buffer.alloc(1024);

console.log("准备打开已存在的文件!");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("文件打开成功4444!");
   console.log("准备读取文件4444:");
   fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
      if (err){
         console.log(err);
      }
      console.log(bytes + "  字节被读取");
      
      // 仅输出读取的字节
      if(bytes > 0){
         console.log(buf.slice(0, bytes).toString());
      }
   });
});


/**
 *5 异步关闭文件
 * fs.close(fd, callback)
 * 该方法使用了文件描述符fd来读取文件。
 * 参数
 * fd - 通过 fs.open() 方法返回的文件描述符。
 * callback - 回调函数,没有参数
 */
var fs = require("fs");
var buf = new Buffer.alloc(1024);

console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("文件打开成功!");
   console.log("准备读取文件!");
   fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
      if (err){
         console.log(err);
      }

      // 仅输出读取的字节
      if(bytes > 0){
         console.log(buf.slice(0, bytes).toString());
      }

      // 关闭文件
      fs.close(fd, function(err){
         if (err){
            console.log(err);
         } 
         console.log("文件关闭成功5555");
      });
   });
});


/**
 * 6异步截取文件
 * fs.ftruncate(fd,len,callback) 截取后破坏原文件
 * 参数:
 * fd - 通过 fs.open() 方法返回的文件描述符。
 * len - 文件内容截取的长度。
 * callback - 回调函数,没有参数。
 */
var fs5 = require("fs");
var buf = new Buffer.alloc(1024);

console.log("准备打开文件!");
fs5.open('input5.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("文件打开成功!");
   console.log("截取10字节内的文件内容,超出部分将被去除。");
   
   // 截取文件
   fs5.ftruncate(fd, 10, function(err){
      if (err){
         console.log(err);
      } 
      console.log("文件截取成功。");
      console.log("读取相同的文件"); 
      fs5.read(fd, buf, 0, buf.length, 0, function(err, bytes){
         if (err){
            console.log(err);
         }

         // 仅输出读取的字节
         if(bytes > 0){
            console.log(buf.slice(0, bytes).toString());
         }

         // 关闭文件
         fs5.close(fd, function(err){
            if (err){
               console.log(err);
            } 
            console.log("文件关闭成功!");
         });
      });
   });
});

/**
 * 6删除文件
 * fs.unlink(path, callback)
 */
console.log("准备删除文件!");
fs.unlink('xxx', function(err) {
   if (err) {
       return console.error(err,'333333');
   }
   console.log("文件删除成功!");
});

/**
 * 7创建目录
 * fs.mkdir(path[, options], callback)
 * 参数
 * path文件路径
 * options 参数可以是:
    recursive - 是否以递归的方式创建目录,默认为 false。
    mode - 设置目录权限,默认为 0777。
 *callback - 回调函数,没有参数。
 */

console.log('创建目录./test/ee')
// test目录必须存在
fs.mkdir('./test/ee',function(err){
    if(err){
        return console.error(err,'创建目录报错')
    }
    console.log('目录创建成功')
})

/**
 * 8读取目录
 * fs.readdir(path, callback)
 * 略
 * callback - 回调函数,回调函数带有两个参数err, files,err 为错误信息,files 为 目录下的文件数组列表。
 */
console.log("查看 /test 目录");
fs.readdir("../nodejs/",function(err, files){
   if (err) {
       return console.error(err,'99999');
   }
   files.forEach( function (file){
       console.log( file ,'文件目录 读取999');
   });
});

/**
 * 删除目录
 * fs.rmdir(path, callback)
 * callback没有参数
 * 
 */


fs.rmdir("./test/ee",function(err){
   if (err) {
       return console.error(err);
   }
   console.log("读取 /test 目录");
   fs.readdir(".test/",function(err, files){
      if (err) {
          return console.error(err);
      }
      files.forEach( function (file){
          console.log( file );
      });
   });
});

数据库

mysql

php

php

你可能感兴趣的:(node.js,node.js,学习,npm)