node常用的模块(四)

1.url概念、组成

url:统一资源定位符

┌─────────────────────────────────────────────────────────────────────────────────────────────┐
│                                            href                                             │
├──────────┬──┬─────────────────────┬─────────────────────┬───────────────────────────┬───────┤
│ protocol │  │        auth         │        host         │           path            │ hash  │
│          │  │                     ├──────────────┬──────┼──────────┬────────────────┤       │
│          │  │                     │   hostname   │ port │ pathname │     search     │       │
│          │  │                     │              │      │          ├─┬──────────────┤       │
│          │  │                     │              │      │          │ │    query     │       │
"  https:   //    user   :   pass   @ sub.host.com : 8080   /p/a/t/h  ?  query=string   #hash "
│          │  │          │          │   hostname   │ port │          │                │       │
│          │  │          │          ├──────────────┴──────┤          │                │       │
│ protocol │  │ username │ password │        host         │          │                │       │
├──────────┴──┼──────────┴──────────┼─────────────────────┤          │                │       │
│   origin    │                     │       origin        │ pathname │     search     │ hash  │
├─────────────┴─────────────────────┴─────────────────────┴──────────┴────────────────┴───────┤
│                                            href                                             │
└─────────────────────────────────────────────────────────────────────────────────────────────┘

1.node常用的内置模块

  1. URL 网址解析,解析URL相关网址信息
    • url.parse(urlString,options)
    • url.format(urlObject)
    • url.resolve(from, to)

方法一:将一个url地址变成一个对象
url.parse(urlString,options);
第一个参数填的是一个ulr地址
第二个参数默认是false,如果你设置成true,那就可以将上图中url组成的query转成对象的形式

//url模块讲解

var url=require('url');


var str='http://www.alibaba.com:4000/api/home/a?key=hello&token=124#banner'


var obj=url.parse(str,true);
// 如果第二个参数为true,就表示,把url的query解析成对象形式。

console.log(obj);

/*
obj.protocal  协议  http:
obj.host      域    www.alibaba.com:4000
obj.hostname  域名  www.alibaba.com
obj.port     端口号 4000
obj.hash      哈希  #banner

obj.query:    参数: key=hello&token=124  或者  {key:'hello',token:124}

obj.pathname :    路径   /api/home/a

*/

方法二:将对象(格式正确)转化成一个url地址
url.format(URL,options)
options -->{ }
auth 如果序列化的URL字符串应该包含用户名和密码为true,否则为false。默认为true。
fragment 如果序列化的URL字符串应该包含分段为true,否则为false。默认为true。
search 如果序列化的URL字符串应该包含搜索查询为true,否则为false。默认为true。
unicode true 如果出现在URL字符串主机元素里的Unicode字符应该被直接编码而不是使用Punycode编码为true,默认为false。
new URL('https://a:b@你好你好?abc#foo')返回一个URL对象
虽然URL对象的toString()方法和href属性都可以返回URL的序列化的字符串。然而,两者都不可以被自定义。而url.format(URL, options)方法允许输出的基本自定义。

const { URL } = require('url');
const myURL = new URL('https://a:b@你好你好?abc#foo');
 
console.log(myURL.href);
  // 输出 https://a:b@xn--6qqa088eba/?abc#foo
 
console.log(myURL.toString());
  // 输出 https://a:b@xn--6qqa088eba/?abc#foo
 
console.log(url.format(myURL, { fragment: false, unicode: true, auth: false }));
  // 输出 'https://你好你好/?abc'

方法三 为URL或 href 插入 或 替换原有的标签
url.resolve(from, to)
接收参数:
from 源地址
to 需要添加或替换的标签

var url = require('url');

var a = url.resolve('/one/two/three', 'four') ,

b = url.resolve('http://example.com/', '/one'),

c = url.resolve('http://example.com/one', '/two');

console.log(a +","+ b +","+ c);

//输出结果:

///one/two/four

//http://example.com/one

//http://example.com/two

  1. fs 文件模块
    文件写入
    Node中文件读取的方式主要有:

    1. fs.readFile(file[, options], callback(error, data))
    fs.readFile('c:\\demo\1.txt', 'utf8', (err, data) => {
      if (err) throw err;
      console.log(data);
    });
    
    1. fs.readFileSync(file[, options])
    try {
      const data = fs.readFileSync('c:\\demo\1.txt', 'utf8');
      console.log(data);
    } catch(e) {
      // 文件不存在,或者权限错误
      throw e;
    }
    
    1. fs.createReadStream(path[, options])
    const stream = fs.createReadStream('c:\\demo\1.txt');
    let data = ''
    stream.on('data', (trunk) => {
      data += trunk;
    });
    stream.on('end', () => {
      console.log(data);
    });
    

    文件写入
    Node中文件写入的方式主要有:

    1. fs.writeFile(file, data[, options], callback(error))
    fs.writeFile('c:\\demo\a.txt', new Date(), (error) => {
      console.log(error);
    });
    
    1. fs.writeFileSync(file, data[, options])
    try {
      fs.writeFileSync('c:\\demo\a.txt', new Date());
    } catch (error) {
      // 文件夹不存在,或者权限错误
      console.log(error);
    }
    
    1. fs.createWriteStream(path[,option])
    var streamWriter = fs.createWriteStream('c:\\demo\a.txt');
    setInterval(() => {
      streamWriter.write(`${new Date}\n`, (error) => {
        console.log(error);
      });
    }, 1000);
    
  2. path模块

    1. path.basename(path[, ext])
      • path路径
      • ext可选的文件扩展名
      • path.basename() 方法返回一个 path 的最后一部分
    path.basename('/foo/bar/baz/asdf/quux.html');
    // 返回: 'quux.html'
    
    path.basename('/foo/bar/baz/asdf/quux.html', '.html');
    // 返回: 'quux'
    
    1. path.dirname(path)

      • path.dirname() 方法返回一个 path 的目录名
      path.dirname('/foo/bar/baz/asdf/quux');
      // 返回: '/foo/bar/baz/asdf'
      

      如果 path 不是一个字符串,则抛出 TypeError。

      注意:只能返回目录名,并不能返回目录的详细信息

    2. path.extname(path)
      path.extname() 方法返回 path 的扩展名

      path.extname('index.html');
      // 返回: '.html'
      
      path.extname('index.coffee.md');
      // 返回: '.md'
      
      path.extname('index.');
      // 返回: '.'
      
      path.extname('index');
      // 返回: ''
      
      path.extname('.index');
      // 返回: ''
      
    3. path.join([...paths])
      path.join() 方法使用平台特定的分隔符把全部给定的 path 片段连接到一起,并规范化生成的路径。

       path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
      	// 返回: '/foo/bar/baz/asdf'
      	
      	path.join('foo', {}, 'bar');
      	// 抛出 'TypeError: Path must be a string. Received {}'
      
    4. path.normalize(path)
      path.normalize() 方法会规范化给定的 path,并解析 ‘…’ 和 ‘.’ 片段

    5. path.parse(path)
      path.parse() 方法返回一个对象,对象的属性表示 path 的元素。 尾部文件分隔符会被忽略
      返回的对象有以下属性
      dir
      root
      base
      name
      ext

       path.parse('C:\\path\\dir\\file.txt');
       		// 返回:
       		// { root: 'C:\\',
       		//   dir: 'C:\\path\\dir',
       		//   base: 'file.txt',
       		//   ext: '.txt',
       		//   name: 'file' }
      
      
      
  3. QueryString 参数处理

    1. querystring.escape(str)
    2. querystring.unescape(str)
    3. querystring.parse(str[, sep[, eq[, options]]])
    4. querystring.stringify(obj[, sep[, eq[, options]]])

queryString用于解析与格式化 URL 查询字符串
方法一:querystring.escape(str)
对给定的 str 进行 URL 编码。

方法二:querystring.unescape(str)
对给定的 str 进行 URL 解码。

方法三:querystring.stringify(obj[, sep[, eq[, options]]])
将对象转化成字符串
sep 第二个参数 用于界定查询字符串中的键值对的子字符串。默认为 ‘&’。
eq 第三个参数 用于界定查询字符串中的键与值的子字符串。默认为 ‘=’。
options
encodeURIComponent 把对象中的字符转换成查询字符串时使用的函数。默认为 querystring.escape()。该方法通过遍历给定的 obj 对象的自身属性,生成 URL 查询字符串。

// 假设存在 gbkEncodeURIComponent 函数。
querystring.stringify({ w: '中文', foo: 'bar' }, null, null,
                      { encodeURIComponent: gbkEncodeURIComponent });

方法四:querystring.parse(str[, sep[, eq[, options]]])
将query字符串装华为对象
sep 第二个参数 用于界定查询字符串中的键值对的子字符串。默认为 ‘&’。
eq 第三个参数 用于界定查询字符串中的键与值的子字符串。默认为 ‘=’。
options
decodeURIComponent 解码查询字符串的字符时使用的函数。默认为 querystring.unescape()。
maxKeys 指定要解析的键的最大数量。指定为 0 则不限制。默认为 1000。

  1. HTTP 模块概要

    http.createServer([options][, requestListener])

2. node中的异步和同步

fs模块对文件的几乎所有操作都有同步和异步两种形式
例如:readFile() 和 readFileSync()
区别:
同步调用会阻塞代码的执行,异步则不会
异步调用会将读取任务下达到任务队列,直到任务执行完成才会回调
异常处理方面,同步必须使用 try catch 方式,异步可以通过回调函数的第一个参数

 	var fs=require('fs')
 	console.time('sync');
 	try {
 	  var data = fs.readFileSync('./c.txt');
 	  console.log(data);
 	} catch (error) {
 	  throw error;
 	}
 	console.timeEnd('sync');
 	console.time('async');
 	fs.readFile('./c.txt',(error, data) => {
 	  if (error) throw error;
 	  console.log(data);
 	});
 	console.timeEnd('async');

3.自己写一个node服务器

  1. 普通静态资源服务器
var http=require('http');
//文件模块  操作文件  读取文件,写入文件
var fs=require('fs');
function read(str,res){
     fs.readFile(str,function(err,data){
        if(!err){
       res.write(data);
       res.end();
        }
  })
}
var server=http.createServer(function(req,res){   //   /img/2.gif
    //接受请求, 做出应有
    
    console.log(req.url);//请求路径   端口后面的,参数前面的   /     /favicon.ico
    if(req.url=='/'){
        read('./index.html',res);
    }else if(req.url=='/favicon.ico'){
        read('./img/ico.png',res);
    }else{
        read('.'+req.url,res);  //  read('.'+'/img/2.gif',res)
    }
    
});
//三个参数,  参数一:端口号(取值范围:0-65535,0-1024系统保留端口,80端口可以省略)
//参数二:域名(ip)
//参数三:回调函数
server.listen(3001,'127.0.0.1',function(err){
    //err 错误对象参数   err-->null   err--->{error:xxx}
    if(!err){//正确
      console.log('服务器成功运行在127.0.0.1:3000上')
    }
})


  1. 带登录接口的服务器
  • index.html文件

    <!-- action提交地址 -->
    <!-- get方式请求特点:1,把参数追加在url后面 2. 明文可见(不安全)3.大小大约为4k-->
    <form action="/api/login" method="get">
    
        用户名:<input type="text" name="user">
    
        密码:<input type="text" name="pass">
    
    
        <button type="submit">登录</button>
    
    </form>
    
    
  • home.html文件

        <!DOCTYPE html>
      	<html lang="en">
      	<head>
      	    <meta charset="UTF-8">
      	    <meta name="viewport" content="width=device-width, initial-scale=1.0">
      	    <meta http-equiv="X-UA-Compatible" content="ie=edge">
      	    <title>Document</title>
      	</head>
      	<body>
      	
      	    <h1>我是首页</h1>
      	    
      	</body>
      	</html>
    
  • server.js文件

       var http=require('http');
      var fs=require('fs');
      // 处理url
      var url=require('url');
      var json=[{user:'tom',pass:'123456'},{user:'kity',pass:'123'}];
      function read(str,res){
          fs.readFile(str,function(err,data){
              if(!err){
                  res.write(data);
                  res.end();
              }
          })
      }
      var server=http.createServer(function(req,res){
         // url.parse(参数一:要解析的地址,是否把参数字符串解析成对象)
            var obj=url.parse(req.url,true)
             
            var pathname=obj.pathname;// 请求路径
            var query=obj.query; // 请求参数  字符 ,对象
          //console.log(req.url); /api/login?user=tom&pass=12345
    
          if(pathname=='/'||pathname=='/index.html'){
                 read('./index.html',res);
          }else if(pathname=='/api/login'){  // 登录
                 for(var i=0;i<json.length;i++){
                      	                if(json[i].user==query.user&&json[i].pass==query.pass){
                               read('./index2.html',res);
                               return;
                      }
                 }
      
                 res.setHeader('Content-Type','text/plain;charset=utf-8');
                 res.write('登录失败');
                 res.end();
          }
            
      })
      
      server.listen(3000,function(err){
          if(!err)console.log('服务器成功运行在3000端口上');
      })
    
原创文章 56 获赞 55 访问量 9645

猜你喜欢

转载自blog.csdn.net/weixin_43638968/article/details/105620484