当前位置:   article > 正文

Node API介绍与简单使用

node api

Node教程

什么是NodeJS

JS是脚本语言,脚本语言都需要一个解析器才能运行。对于写在HTML页面里的JS,浏览器充当了解析器的角色。而对于需要独立运行的JS,NodeJS就是一个解析器。

每一种解析器都是一个运行环境,不但允许JS定义各种数据结构,进行各种计算,还允许JS使用运行环境提供的内置对象和方法做一些事情。例如运行在浏览器中的JS的用途是操作DOM,浏览器就提供了document之类的内置对象。而运行在NodeJS中的JS的用途是操作磁盘文件或搭建HTTP服务器,NodeJS就相应提供了fshttp等内置对象。

Node官网

官网API

中文翻译

Buffer

在引入 TypedArray 之前,JavaScript 语言没有用于读取或操作二进制数据流的机制。 Buffer 类是作为 Node.js API 的一部分引入的,用于在 TCP 流、文件系统操作、以及其他上下文中与八位字节流进行交互。

Buffer对象是Node处理二进制数据的一个接口。它是Node原生提供的全局对象,可以直接使用,不需要require(‘buffer’),我的理解其实buffer就是个字节数组。

  • 实例化
    • Buffer.from(array)
    • Buffer.from(string)
    • Buffer.alloc(size)
  • 功能方法
    • Buffer.isEncoding() 判断是否支持该编码
    • Buffer.isBuffer() 判断是否为Buffer
    • Buffer.byteLength() 返回指定编码的字节长度,默认utf8
    • Buffer.concat() 将一组Buffer对象合并为一个Buffer对象
  • 实例方法
    • write() 向buffer对象中写入内容

    • slice() 截取新的buffer对象

    • toString() 把buf对象转成字符串

    • toJson() 把buf对象转成json形式的字符串

      toJSON方法不需要显式调用,当JSON.stringify方法调用的时候会自动调用toJSON方法

核心模块API

路径操作Path

path 模块提供用于处理文件路径和目录路径的实用工具。 它可以使用以下方式访问:

const path = require('path');
  • 1
Path对象
const path = require('path');
console.log(path)
// 结果:
// { resolve: [Function: resolve],
//   normalize: [Function: normalize],
//   isAbsolute: [Function: isAbsolute],
//   join: [Function: join],
//   relative: [Function: relative],
//   toNamespacedPath: [Function: toNamespacedPath],
//   dirname: [Function: dirname],
//   basename: [Function: basename],
//   extname: [Function: extname],
//   format: [Function: format],
//   parse: [Function: parse],
//   sep: '\\',
//   delimiter: ';',
//   win32: [Circular],
//   posix:
//    { resolve: [Function: resolve],
//      normalize: [Function: normalize],
//      isAbsolute: [Function: isAbsolute],
//      join: [Function: join],
//      relative: [Function: relative],
//      toNamespacedPath: [Function: toNamespacedPath],
//      dirname: [Function: dirname],
//      basename: [Function: basename],
//      extname: [Function: extname],
//      format: [Function: format],
//      parse: [Function: parse],
//      sep: '/',
//      delimiter: ':',
//      win32: [Circular],
//      posix: [Circular],
//      _makeLong: [Function: toNamespacedPath] },
//   _makeLong: [Function: toNamespacedPath] }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
获取路径的最后一部分path.basename
console.log(path.basename('/foo/bar/baz/asdf/quux.html'));
// 返回: 'quux.html'
console.log(path.basename('/foo/bar/baz/asdf/quux.html', '.html'));
// 返回: 'quux'
  • 1
  • 2
  • 3
  • 4
获取路径path.dirname
console.log(__dirname);
// 返回  此文件目录的绝对路径C:\Users\xiaox\Desktop\code
console.log(__filename)
// 返回  此文件的绝对路径C:\Users\xiaox\Desktop\code\1.js
console.log(path.dirname('/abc/qqq/www/abc'));
// 返回 /abc/qqq/www
console.log(path.dirname('/abc/qqq/www/abc.txt'));
// 返回 /abc/qqq/www
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
获取扩展名path.extname(path)
console.log(path.extname('index.html'));
// 返回 .html
  • 1
  • 2
路径的格式化处理path.format(pathObject)与path.parse(path)

path.format(pathObject) obj->string

let objpath = { 
  root: 'C:\\',
  dir:
   'C:\\Users\\xiaox\\Desktop\\code',
  base: '1.js',
  ext: '.js',
  name: '1' 
};
console.log(path.format(objpath));
// 返回C:\Users\xiaox\Desktop\code\1.js
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

当为 pathObject 提供属性时,注意以下组合,其中一些属性优先于另一些属性:

  • 如果提供了 pathObject.dir,则忽略 pathObject.root
  • 如果 pathObject.base 存在,则忽略 pathObject.extpathObject.name

path.parse(path) string->obj

console.log(path.parse(__filename));
/*
{ root: 'C:\\',
  dir:
   'C:\\Users\\xiaox\\Desktop\\code',
  base: '1.js',
  ext: '.js',
  name: '1' 
}
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
判断是否为绝对路径path.isAbsolute(path)
console.log(path.isAbsolute('/foo/bar'));
// 返回true
console.log(path.isAbsolute('C:/foo/..'));
// 返回true
  • 1
  • 2
  • 3
  • 4
拼接路径path.join([…paths])

(…表示上层路径;.表示当前路径),在连接路径的时候会格式化路径

path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// 返回: '/foo/bar/baz/asdf'

path.join('foo', {}, 'bar');
// 抛出 'TypeError: Path must be a string. Received {}'
  • 1
  • 2
  • 3
  • 4
  • 5
规范化路径path.normalize(path)
console.log(path.normalize('/foo/bar//baz/asdf/quux/..'));
// 返回: '/foo/bar/baz/asdf'
console.log(path.normalize('C:\\temp\\\\foo\\bar\\..\\'));
// 返回: 'C:\\temp\\foo\\'
  • 1
  • 2
  • 3
  • 4
计算相对路径path.relative(from, to)
console.log(path.relative('/data/orandea/test/aaa','/data/orandea/impl/bbb'));
// 返回: '../../impl/bbb'
console.log(path.relative('C:\\orandea\\test\\aaa','C:\\orandea\\impl\\bbb'));
// 返回: '..\\..\\impl\\bbb'
  • 1
  • 2
  • 3
  • 4
解析路径path.resolve([…paths])

给定的路径序列从右到左进行处理,每个后续的 path 前置,直到构造出一个绝对路径

path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// 如果当前工作目录是 /home/myself/node,
// 则返回 '/home/myself/node/wwwroot/static_files/gif/image.gif'
  • 1
  • 2
  • 3
两个特殊属性path.seppath.delimiter
console.log(path.delimiter);//表示路径分隔符(windows是\ Linux是/)POSIX 上:

console.log(process.env.PATH);
// 打印: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin'

process.env.PATH.split(path.delimiter);
// 返回: ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin']
在 Windows 上:

console.log(process.env.PATH);
// 打印: 'C:\Windows\system32;C:\Windows;C:\Program Files\node\'

process.env.PATH.split(path.delimiter);
// 返回: ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\']
------------------------------------------------------------------------------
console.log(path.sep);//环境变量分隔符(windows中使用; linux中使用:)POSIX 上:

'foo/bar/baz'.split(path.sep);
// 返回: ['foo', 'bar', 'baz']
在 Windows 上:

'foo\\bar\\baz'.split(path.sep);
// 返回: ['foo', 'bar', 'baz']

在 Windows 上,正斜杠(/)和反斜杠(\)都被接受为路径片段分隔符。 但是, path 方法只添加反斜杠(\)。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

文件操作Fs

/*
    异步I/O input/output
    1、文件操作
    2、网络操作

    在浏览器中也存在异步操作:
    1、定时任务
    2、事件处理
    3、Ajax回调处理

    js的运行时单线程的
    引入事件队列机制

    Node.js中的事件模型与浏览器中的事件模型类似
    单线程+事件队列

    Node.js中异步执行的任务:
    1、文件I/O
    2、网络I/O

    基于回调函数的编码风格
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
查看文件状态及信息获取fs.Stats 类fs.stat/fs.statSync
Stats {
  dev: 2114,//该文件的设备的数字标识符
  ino: 48064969,//文件系统特定的文件索引节点编号
  mode: 33188,//描述文件类型和模式的位字段
  nlink: 1,//文件存在的硬链接数
  uid: 85,//拥有该文件(POSIX)的用户的数字型用户标识符
  gid: 100,//拥有该文件(POSIX)的群组的数字型群组标识符
  rdev: 0,//如果文件被视为特殊文件,则此值为数字型设备标识符
  size: 527,//文件的大小(以字节为单位)
  blksize: 4096,//用于 I/O 操作的文件系统块的大小
  blocks: 8,//为此文件分配的块数
  atimeMs: 1318289051000.1,//表明上次访问此文件的时间戳,以 POSIX 纪元以来的毫秒数表示
  mtimeMs: 1318289051000.1,//表明上次修改此文件的时间戳,以 POSIX 纪元以来的毫秒数表示
  ctimeMs: 1318289051000.1,//表明上次更改文件状态的时间戳,以 POSIX 纪元以来的毫秒数表示
  birthtimeMs: 1318289051000.1,//表明此文件的创建时间的时间戳,以 POSIX 纪元以来的毫秒数表示
  atime: Mon, 10 Oct 2011 23:24:11 GMT,//表明上次访问此文件的时间戳 文件访问时间
  mtime: Mon, 10 Oct 2011 23:24:11 GMT,//表明上次修改此文件的时间戳 文件数据发生变化的时间
  ctime: Mon, 10 Oct 2011 23:24:11 GMT,//表明上次更改文件状态的时间戳 文件的状态信息发生变化的时间(比如文件的权限)
  birthtime: Mon, 10 Oct 2011 23:24:11 GMT //表示此文件的创建时间的时间戳 文件创建的时间
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

常用判断是否为常规文件stats.isFile()和文件目录stats.isDirectory()返回布尔值

fs.stat(path[, options], callback)

// const fs = require('fs');

// const pathsToCheck = ['./txtDir', './txtDir/file.txt'];

//异步操作
// for (let i = 0; i < pathsToCheck.length; i++) {
//   fs.stat(pathsToCheck[i], function(err, stats) {
//     if(stats.isFile()){
//         console.log(pathsToCheck[i]+'---文件');
//         console.log(stats)
//     }else if(stats.isDirectory()){
//         console.log(pathsToCheck[i]+'---目录');
//         console.log(stats)
//     }else{
//         console.log(err)
//     }
//   });
// }

// 同步操作Sync
// console.log(1);
// let ret = fs.statSync('./data.txt');
// console.log(ret);
// console.log(2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
读文件操作fs.readFile/fs.readFileSync
/*
    读文件操作
*/
const fs = require('fs');
const path = require('path');

let strpath = path.join(__dirname,'data.txt');
fs.readFile(strpath,(err,data)=>{
    if(err) return;
    console.log(data.toString());
});

如果有第二个参数并且是编码,那么回调函数获取到的数据就是字符串
如果没有第二个参数,那么得到的就是Buffer实例对象
fs.readFile(strpath,'utf8',(err,data)=>{
    if(err) return;
    // console.log(data.toString());
    console.log(data);
});

同步操作
let ret = fs.readFileSync(strpath,'utf8');
console.log(ret);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
写文件操作fs.writeFile/fs.writeFileSync
/*
    写文件操作
*/
const fs = require('fs');
const path = require('path');

// 异步操作
let strpath = path.join(__dirname,'data.txt');
fs.writeFile(strpath,'hello nihao','utf8',(err)=>{
    if(!err){
        console.log('文件写入成功');
    }
});

let buf = Buffer.from('hi');
fs.writeFile(strpath,buf,'utf8',(err)=>{
    if(!err){
        console.log('文件写入成功');
    }
});

// 同步操作
fs.writeFileSync(strpath,'tom and jerry');
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
大文件操作(流式操作)fs.createReadStream/fs.createWriteStream
将文件从一个地方写入另一个地方
const path = require('path');
const fs = require('fs');

let spath = path.join(__dirname,'../03-source','file.zip');
let dpath = path.join('C:\\Users\\www\\Desktop','file.zip');

let readStream = fs.createReadStream(spath);
let writeStream = fs.createWriteStream(dpath);

// 基于事件的处理方式
// $('input[type=button]').on('click',function(){
//     console.log('hello');
// });

方法一
// -----------------------------------
let num = 1;
readStream.on('data',(chunk)=>{
    num++;
    writeStream.write(chunk);
});

readStream.on('end',()=>{
    console.log('文件处理完成'+num);
});

方法二
// -----------------------------------

// pipe的作用直接把输入流和输出流
readStream.pipe(writeStream);

方法三
// ----------------------------------
fs.createReadStream(spath).pipe(fs.createWriteStream(dpath));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
目录操作
  • 创建目录fs.mkdir(path[, mode], callback)/fs.mkdirSync(path[, mode])

    const path = require('path');
    const fs = require('fs');
    // 创建目录
    fs.mkdir(path.join(__dirname,'abc'),(err)=>{
        console.log(err);
    });
    fs.mkdirSync(path.join(__dirname,'hello'));
    
    
    // 创建 /tmp/a/apple 目录,无论是否存在 /tmp 和 /tmp/a 目录。
    // recursive 属性(指示是否应创建父文件夹)的对象
    fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
      if (err) throw err;
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 读取目录fs.readdir(path[, options], callback)/fs.readdirSync(path[, options])

    const path = require('path');
    const fs = require('fs');
    // 读取目录
    fs.readdir(__dirname,(err,files)=>{
        files.forEach((item,index)=>{
            fs.stat(path.join(__dirname,item),(err,stat)=>{
                if(stat.isFile()){
                    console.log(item,'文件');
                }else if(stat.isDirectory()){
                    console.log(item,'目录');
                }
            });
        });
    });
    
    let files = fs.readdirSync(__dirname);
    files.forEach((item,index)=>{
        fs.stat(path.join(__dirname,item),(err,stat)=>{
            if(stat.isFile()){
                console.log(item,'文件');
            }else if(stat.isDirectory()){
                console.log(item,'目录');
            }
        });
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 删除目录fs.rmdir(path, callback)/fs.rmdirSync(path)

    // 删除目录
    fs.rmdir(path.join(__dirname,'abc'),(err)=>{
        console.log(err);
    });
    
    fs.rmdirSync(path.join(__dirname,'qqq'));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
文件操作案例
/*
    文件操作案例(初始化目录结构)
*/
const path = require('path');
const fs = require('fs');

let root = 'C:\\Users\\www\\Desktop';
let fileContent = `
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>welcome to this</div>
</body>
</html>
`;

// 初始化数据
let initData = {
    projectName : 'mydemo',
    data : [{
        name : 'img',
        type : 'dir'
    },{
        name : 'css',
        type : 'dir'
    },{
        name : 'js',
        type : 'dir'
    },{
        name : 'index.html',
        type : 'file'
    }]
}

// 创建项目跟路径
fs.mkdir(path.join(root,initData.projectName),(err)=>{
    if(err) return;
    // 创建子目录和文件
    initData.data.forEach((item)=>{
        if(item.type == 'dir'){
            // 创建子目录
            fs.mkdirSync(path.join(root,initData.projectName,item.name));
        }else if(item.type == 'file'){
            // 创建文件并写入内容
            fs.writeFileSync(path.join(root,initData.projectName,item.name),fileContent);
        }
    });
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

服务器操作Http

传统的动态网站开发需要应用软件
PHP : Apache + php模块
java :Tomcat 、Weblogic
Node.js  : 不需要应用软件(可以自己实现)

/*
    Node.js的Web开发相关的内容:
    1、Node.js不需要依赖第三方应用软件(Apache),可以基于api自己实现
    2、实现静态资源服务器
    3、路由处理
    4、动态网站
    5、模板引擎
    6、get和post参数传递和处理

    Web开发框架:express
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
创建服务器[http.createServer(options][, requestListener])
const http = require('http');
// // 创建服务器实例对象
let server = http.createServer();
console.log(server)

Server {
  _events:
   [Object: null prototype] { connection: [Function: connectionListener] },
  _eventsCount: 1,
  _maxListeners: undefined,
  _connections: 0,
  _handle: null,
  _usingWorkers: false,
  _workers: [],
  _unref: false,
  allowHalfOpen: true,
  pauseOnConnect: false,
  httpAllowHalfOpen: false,
  timeout: 120000,//超时时间(以毫秒为单位)。默认值: 120000(2 分钟)
  keepAliveTimeout: 5000,//超时时间(以毫秒为单位)。默认值: 5000(5 秒)更改此值仅影响到服务器的新连接,而不影响任何现有连接
  maxHeadersCount: null,//限制最大传入请求头数。 如果设置为 0,则不会应用任何限制  默认值: 2000
  headersTimeout: 40000,//限制解析器等待接收完整 HTTP 请求头的时间 默认值: 40000
  [Symbol(IncomingMessage)]:
   { [Function: IncomingMessage]
     super_:
      { [Function: Readable]
        ReadableState: [Function: ReadableState],
        super_: [Function],
        _fromList: [Function: fromList] } },
  [Symbol(ServerResponse)]:
   { [Function: ServerResponse] super_: { [Function: OutgoingMessage] super_: [Function] } },
  [Symbol(asyncId)]: -1 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

http.createServer方法会返回一个http.Server对象实例,requestListener可选参数传入时,将做为http.Server对象'request'事件的监听器。

发送请求http.server类下的request事件

每次有请求时都会触发。 每个连接可能有多个请求(在 HTTP Keep-Alive 连接的情况下)。

/*
    初步实现服务器功能
*/
const http = require('http');
// -----------------------------
方法一:
// 创建服务器实例对象
let server = http.createServer();
console.log(server)
// 绑定请求事件
server.on('request',(req,res)=>{
    res.end('hello');
});
// 监听端口
server.listen(3000);
// -----------------------------
方法二:
http.createServer((req,res)=>{
    res.end('ok');//response.end([data[, encoding]][, callback])
}).listen(3000,'192.168.0.106',()=>{
    console.log('running...');
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

res.end()就是上述response类的方法;[response.end(data[, encoding]][, callback])

res.end('ok','utf-8',()=>{
	console.log('一切正常')
});
  • 1
  • 2
  • 3
启动 HTTP 服务器监听连接server.listen()

此方法与 net.Server 中的 server.listen() 相同。

上一例子也可,详细可见官方api
server.listen({
  host: 'localhost',
  port: 80,
  exclusive: true
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
请求路径分发http.ServerResponse 类

1、req对象是Class: http.IncomingMessage的实例对象
2、res对象是Class: http.ServerResponse的实例对象

const http = require('http');
http.createServer((req,res)=>{
    // req.url可以获取URL中的路径(端口之后部分)
    // res.end(req.url);
    if(req.url.startsWith('/index')){
        // write向客户端响应内容,可以写多次
        res.write('hello');
        res.write('hi');
        res.write('nihao');
        // end方法用来完成响应,只能执行一次
        res.end();
    }else if(req.url.startsWith('/about')){
        res.end('about');
    }else{
        res.end('no content');
    }
}).listen(3000,'192.168.0.106',()=>{
    console.log('running...');
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

res.write()就是上述response类的方法;[response.write(chunk, encoding][, callback])

/*
    响应完整的页面信息
*/
const http = require('http');
const path = require('path');
const fs = require('fs');

// 根据路径读取文件的内容,并且响应到浏览器端
let readFile = (url,res) => {
    fs.readFile(path.join(__dirname,'www',url),'utf8',(err,fileContent)=>{
        if(err){
            res.end('server error');
        }else{
            res.end(fileContent);
        }
    });
}

http.createServer((req,res)=>{
    // 处理路径的分发
    if(req.url.startsWith('/index')){
        readFile('index.html',res);
    }else if(req.url.startsWith('/about')){
        readFile('about.html',res);
    }else if(req.url.startsWith('/list')){
        readFile('list.html',res);
    }else{
        // 设置相应类型和编码
        res.writeHead(200,{
            'Content-Type':'text/plain; charset=utf8'
        });
        res.end('页面被狗狗叼走了');
    }
}).listen(3000,'192.168.0.106',()=>{
    console.log('running...');
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

设置响应头[response.writeHead(statusCode, statusMessage][, headers])response.setHeader(name, value)

当使用 response.setHeader() 设置响应头时,它们将与传给 response.writeHead() 的任何响应头合并,其中 response.writeHead() 的响应头优先。

// 返回 content-type = text/plain
const server = http.createServer((req, res) => {
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('X-Foo', 'bar');
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('ok');
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

解析接口操作URL

URL对象
const url = require('url');
console.log(url)

{ Url: [Function: Url],
  parse: [Function: urlParse],
  resolve: [Function: urlResolve],
  resolveObject: [Function: urlResolveObject],
  format: [Function: urlFormat],
  URL: [Function: URL],
  URLSearchParams: [Function: URLSearchParams],
  domainToASCII: [Function: domainToASCII],
  domainToUnicode: [Function: domainToUnicode],
  pathToFileURL: [Function: pathToFileURL],
  fileURLToPath: [Function: fileURLToPath] 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
GET参数处理[url.parse(urlString, parseQueryString[, slashesDenoteHost]])

parse方法的作用就是把URL字符串转化为对象

const url = require('url');
let str = 'http://www.baidu.com/abc/qqq?flag=123&keyword=java';
let ret = url.parse(str)
console.log(ret)
//以下可以参展urlObject
Url {
  protocol: 'http:',//协议
  slashes: true,// url里characters (/)的是true,否则false
  auth: null,//用户名和密码
  host: 'www.baidu.com',//主机地址 主机名+端口
  port: null,//端口
  hostname: 'www.baidu.com',//主机名
  hash: null,//characters (#)
  search: '?flag=123&keyword=java',//查询参数
  query: 'flag=123&keyword=java',//去掉?的查询参数
  pathname: '/abc/qqq',//路径名
  path: '/abc/qqq?flag=123&keyword=java',//路径
  href: 'http://www.baidu.com/abc/qqq?flag=123&keyword=java' //完整url
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

第二个参数parseQueryString其实将query.parse了

const url = require('url');
let str = 'http://www.baidu.com/abc/qqq?flag=123&keyword=java';
let ret = url.parse(str,true)
console.log(ret)
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'www.baidu.com',
  port: null,
  hostname: 'www.baidu.com',
  hash: null,
  search: '?flag=123&keyword=java',
  query: [Object: null prototype] { flag: '123', keyword: 'java' },
  pathname: '/abc/qqq',
  path: '/abc/qqq?flag=123&keyword=java',
  href: 'http://www.baidu.com/abc/qqq?flag=123&keyword=java' }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
GET参数处理url.format(URL[, options])

format的作用就是把对象转化为标准的URL字符串

url.format({
  protocol: 'https',
  hostname: 'example.com',
  pathname: '/some/path',
  query: {
    page: 1,
    format: 'json'
  }
});

// => 'https://example.com/some/path?page=1&format=json'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

查询字符串Querystring

querystring 模块提供用于解析和格式化 URL 查询字符串的实用工具。 它可以使用以下方式访问:

const querystring = require('querystring');
  • 1
POST参数处理 querystring.parse(str[, sep[, eq[, options]]])

parse方法的作用就是把字符串转成对象

  • str string 要解析的 URL 查询字符串。
  • sep string 用于在查询字符串中分隔键值对的子字符串。默认值: '&'
  • eq string 用于在查询字符串中分隔键和值的子字符串。默认值: '='
  • options object
    • decodeURIComponent funciton 解码查询字符串中的百分比编码字符时使用的函数。默认值: querystring.unescape()
    • maxKeys number 指定要解析的键的最大数量。指定 0 可移除键的计数限制。默认值: 1000

querystring.parse() 方法将 URL 查询字符串 str 解析为键值对的集合。

例如,查询字符串 'foo=bar&abc=xyz&abc=123' 被解析为:

const querystring = require('querystring');
let param = 'foo=bar&abc=xyz&abc=123';
let obj = querystring.parse(param);
console.log(obj);
{
  foo: 'bar',
  abc: ['xyz', '123']
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

querystring.parse() 方法返回的对象不是原型继承自 JavaScript Object。 这意味着典型的 Object 方法如 obj.toString()obj.hasOwnProperty() 等都没有定义并且不起作用。

POST参数处理 querystring.stringify(str[, sep[, eq[, options]]])

stringify的作用就是把对象转成字符串

  • obj object 要序列化为 URL 查询字符串的对象。
  • sep string 用于在查询字符串中分隔键值对的子字符串。默认值: '&'
  • eq string 用于在查询字符串中分隔键和值的子字符串。默认值: '='
  • options
    • encodeURIComponent function 在查询字符串中将 URL 不安全字符转换为百分比编码时使用的函数。默认值: querystring.escape()

querystring.stringify() 方法通过迭代对象的自身属性从给定的 obj 生成 URL 查询字符串。

它序列化了传入 obj 中的以下类型的值: | | | <string[]> | <number[]> | <boolean[]>。 任何其他输入值都将被强制转换为空字符串。

querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
// 返回 'foo=bar&baz=qux&baz=quux&corge='

querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':');
// 返回 'foo:bar;baz:qux'

let obj1 = {
    flag : '123',
    abc : ['hello','hi']
}
let str1 = querystring.stringify(obj1);
console.log(str1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
简单POST请求案例
const querystring = require('querystring');
const http = require('http');

http.createServer((req,res)=>{
    if(req.url.startsWith('/login')){
        let pdata = '';
        req.on('data',(chunk)=>{
            // 每次获取一部分数据
            pdata += chunk;
        });

        req.on('end',()=>{
            // 这里才能得到完整的数据
            console.log(pdata);
            let obj = querystring.parse(pdata);
            res.end(obj.username+'-----'+obj.password);
        });
    }
}).listen(3000,()=>{
    console.log('running...');
})
//这里可以自己用postman调试
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/68988
推荐阅读
相关标签
  

闽ICP备14008679号