Node.JS学习——学习笔记

Node.JS——学习笔记

2020年02月23日11:52:01

我打算自学NodeJS-通过阅读NodeJS官网来完成。

https://nodejs.org/dist/latest-v13.x/docs/api/

https://www.liaoxuefeng.com/wiki/1022910821149312/1023025235359040

初识Node.js

Node.js® 是一个基于 Chrome V8 引擎 的 JavaScript 运行时。

安装Node.js

下载-安装

运行首个Node.js程序

  1. 创建app.js文件,代码如下
//创建 app.js文件,使用node app.js 运行
const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
  1. 使用node app.js命令,运行Node程序。访问。OK。

    运行成功~

模块(module)

初始模块

  1. 创建代码,认识模块的调用

    'use strict';
    console.log("hello world");
    var s = "Hello";
    function greet(name){
        console.log(s+","+name)
    }
    function greet2(){
        console.log("1")
    }
    module.exports = {
        greet:greet,
        greet2:greet2
    }
    

    这里自己做了一个小实验,关于多模块的引用和单模块引用的区别。

    'use strict';
    //引入hello 模块
    var greet = require('./hello').greet;
    var greet2 = require('./hello').greet2;
    var name = 'Michael';
    greet("大娃");
    greet2();
    

    在这里我想说,万物皆是对象。

  2. 关于局部变量的问题,这里也解释一下。如果看了node的底层module实现源码,确很容易弄懂。

基本模块

global全局对象和process线程对象

**golbal ** 全局对象

在前面的JavaScript课程中,我们已经知道,JavaScript有且仅有一个全局对象,在浏览器中,叫window对象。而在Node.js环境中,也有唯一的全局对象,但不叫window,而叫global,这个对象的属性和方法也和浏览器环境的window不同。

> global.console
{
  log: [Function: bound consoleCall],
  warn: [Function: bound consoleCall],
  dir: [Function: bound consoleCall],
  time: [Function: bound consoleCall],
  timeEnd: [Function: bound consoleCall],
  timeLog: [Function: bound consoleCall],
  trace: [Function: bound consoleCall],
  assert: [Function: bound consoleCall],
  clear: [Function: bound consoleCall],
  count: [Function: bound consoleCall],
  countReset: [Function: bound consoleCall],
  group: [Function: bound consoleCall],
  groupEnd: [Function: bound consoleCall],
  table: [Function: bound consoleCall],
  debug: [Function: bound consoleCall],
  info: [Function: bound consoleCall],
  dirxml: [Function: bound consoleCall],
  error: [Function: bound consoleCall],
  groupCollapsed: [Function: bound consoleCall],
  Console: [Function: Console],
  profile: [Function: profile],
  profileEnd: [Function: profileEnd],
  timeStamp: [Function: timeStamp],
  context: [Function: context],
  ...//大娃手动省略,太多了
}

process 线程对象

process也是Node.js提供的一个对象,它代表当前Node.js进程。

> process
process {
  version: 'v13.9.0',
  versions: {
    node: '13.9.0',
    v8: '7.9.317.25-node.28',
    uv: '1.34.2',
    zlib: '1.2.11',
    brotli: '1.0.7',
    ares: '1.15.0',
    modules: '79',
    nghttp2: '1.40.0',
    napi: '5',
    llhttp: '2.0.4',
    openssl: '1.1.1d',
    cldr: '36.0',
    icu: '65.1',
    tz: '2019c',
    unicode: '12.1'
  },
  arch: 'x64',
  platform: 'darwin',
  release: {
    name: 'node',
    sourceUrl: 'https://nodejs.org/download/release/v13.9.0/node-v13.9.0.tar.gz',
    headersUrl: 'https://nodejs.org/download/release/v13.9.0/node-v13.9.0-headers.tar.gz'
  },
  _rawDebug: [Function: _rawDebug],
  moduleLoadList: [
    ...//大娃手动省略。太多了
  ],
  binding: [Function: binding],
  _linkedBinding: [Function: _linkedBinding],
  _events: [Object: null prototype] {
    newListener: [ [Function: startListeningIfSignal], [Function (anonymous)] ],
    removeListener: [ [Function: stopListeningIfSignal], [Function (anonymous)] ],
    warning: [Function: onWarning],
    SIGWINCH: [Function (anonymous)]
  },
  _eventsCount: 4,
  _maxListeners: undefined,
  domain: [Getter/Setter],
  _exiting: false,
  config: {
    target_defaults: {
      cflags: [],
      default_configuration: 'Release',
      defines: [],
      include_dirs: [],
      libraries: []
    },
    variables: {...}//手动省略
  },
  ...//大娃手动省略,内容太多了
  env: {
   ...//大娃手动省略,内容太多了。
  },
  title: 'node',
  argv: [ '/usr/local/bin/node' ],
  execArgv: [],
  pid: 10379,
  ppid: 6491,
  execPath: '/usr/local/bin/node',
  debugPort: 9229,
  argv0: 'node',
  _preload_modules: [],
  [Symbol(kCapture)]: false
}
    //大娃批注:**一个process,就能查询出当前线程基本上所有的Info**

fs(文件系统模块)

Node.js内置的fs模块就是文件系统模块,负责读写文件。

和所有其它JavaScript模块不同的是,fs模块同时提供了异步和同步的方法。

  1. 异步读文件

    'use strict';
    
    var fs = require('fs');
    
    fs.readFile('sample.txt', 'utf-8', function (err, data) {
        if (err) {
            console.log(err);
        } else {
            console.log(data);
        }
    });
    //请注意,sample.txt文件必须在当前目录下,且文件编码为utf-8。
    
  2. 同步读文件

    除了标准的异步读取模式外,fs也提供相应的同步读取函数。同步读取的函数和异步函数相比,多了一个Sync后缀,并且不接收回调函数,函数直接返回结果。

    'use strict';
    
    var fs = require('fs');
    
    var data = fs.readFileSync('sample.txt', 'utf-8');
    console.log(data);
    // 可见,原异步调用的回调函数的data被函数直接返回,函数名需要改为readFileSync,其它参数不变。
    
  3. 异步写文件

    将数据写入文件是通过fs.writeFile()实现的:

    'use strict';
    
    var fs = require('fs');
    
    var data = 'Hello, Node.js';
    fs.writeFile('output.txt', data, function (err) {
        if (err) {
            console.log(err);
        } else {
            console.log('ok.');
        }
    });
    //writeFile()的参数依次为文件名、数据和回调函数。如果传入的数据是String,默认按UTF-8编码写入文本文件,如果传入的参数是Buffer,则写入的是二进制文件。回调函数由于只关心成功与否,因此只需要一个err参数。
    
  4. 同步写文件

    readFile()类似,writeFile()也有一个同步方法,叫writeFileSync()

    'use strict';
    
    var fs = require('fs');
    
    var data = 'Hello, Node.js';
    fs.writeFileSync('output.txt', data);
    
  5. stat()方法:获取文件或者目录的信息

    如果我们要获取文件大小,创建时间等信息,可以使用fs.stat(),它返回一个Stat对象,能告诉我们文件或目录的详细信息:

    'use strict';
    
    var fs = require('fs');
    
    fs.stat('sample.txt', function (err, stat) {
        if (err) {
            console.log(err);
        } else {
            // 是否是文件:
            console.log('isFile: ' + stat.isFile());
            // 是否是目录:
            console.log('isDirectory: ' + stat.isDirectory());
            if (stat.isFile()) {
                // 文件大小:
                console.log('size: ' + stat.size);
                // 创建时间, Date对象:
                console.log('birth time: ' + stat.birthtime);
                // 修改时间, Date对象:
                console.log('modified time: ' + stat.mtime);
            }
        }
    });
    
  6. 异步还是同步?

    fs模块中,提供同步方法是为了方便使用。那我们到底是应该用异步方法还是同步方法呢?

    由于Node环境执行的JavaScript代码是服务器端代码,所以,绝大部分需要在服务器运行期反复执行业务逻辑的代码,必须使用异步代码,否则,同步代码在执行时期,服务器将停止响应,因为JavaScript只有一个执行线程

    服务器启动时如果需要读取配置文件,或者结束时需要写入到状态文件时,可以使用同步代码,因为这些代码只在启动和结束时执行一次,不影响服务器正常运行时的异步执行。

  7. 自己写的demo

    'use strict';
    var fs = require('fs');
    // 异步读取文件操作
    fs.readFile('test.js','utf-8',function(err,data){
        if(err){
            console.log('error');
        }else{
            console.log(data);
        }
    })
    
    var content = "hello world";
    // 异步写文件操作
    fs.writeFile('write.js',content,function(err){
        if (err) {
            console.log(err);
        } else {
            console.log('ok');
        }
    })
    
    //stat状态查询
    fs.stat('write.js',function (err,stat) {
        if (err) {
            console.log(err);
        } else {
           console.log(stat.size);
        }
    })
    

stream

stream是Node.js提供的又一个仅在服务区端可用的模块,目的是支持“流”这种数据结构。

大娃评价:和java8提供的stream流结构一样。

  1. 读流 ()

    'use strict';
    
    var fs = require('fs');
    
    // 打开一个流:
    var rs = fs.createReadStream('sample.txt', 'utf-8');
    
    rs.on('data', function (chunk) {
        console.log('DATA:')
        console.log(chunk);
    });
    
    rs.on('end', function () {
        console.log('END');
    });
    
    rs.on('error', function (err) {
        console.log('ERROR: ' + err);
    });
    
  2. 写流 ()

    'use strict';
    
    var fs = require('fs');
    
    var ws1 = fs.createWriteStream('output1.txt', 'utf-8');
    ws1.write('使用Stream写入文本数据...\n');
    ws1.write('END.');
    ws1.end();
    
    var ws2 = fs.createWriteStream('output2.txt');
    ws2.write(new Buffer('使用Stream写入二进制数据...\n', 'utf-8'));
    ws2.write(new Buffer('END.', 'utf-8'));
    ws2.end();
    
  3. pipe ()

    'use strict';
    
    var fs = require('fs');
    
    var rs = fs.createReadStream('sample.txt');
    var ws = fs.createWriteStream('copied.txt');
    
    rs.pipe(ws);
    

HTTP

要开发HTTP服务器程序,从头处理TCP连接,解析HTTP是不现实的。这些工作实际上已经由Node.js自带的http模块完成了。应用程序并不直接和HTTP协议打交道,而是操作http模块提供的requestresponse对象。

request对象封装了HTTP请求,我们调用request对象的属性和方法就可以拿到所有HTTP请求的信息;

response对象封装了HTTP响应,我们操作response对象的方法,就可以把HTTP响应返回给浏览器。

  1. 用Node.js实现一个HTTP服务器程序

    'use strict';
    //导入HTTP模块
    var http = require("http");
    //创建服务器对象
    var server = http.createServer(function(request,response) {
        console.log(request.url);
        response.writeHead(200,{'Content-Type':'text/html'});
        response.end('<h1>hello world</h1>');
    });
    server.listen(8080);
    console.log("Server is running at 8080 port");
    

URL

解析URL需要用到Node.js提供的url模块,它使用起来非常简单,通过parse()将一个字符串解析为一个Url对象.

'use strict';

var url = require('url');

console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));

//解析结果如下

Url {
  protocol: 'http:',
  slashes: true,
  auth: 'user:pass',
  host: 'host.com:8080',
  port: '8080',
  hostname: 'host.com',
  hash: '#hash',
  search: '?query=string',
  query: 'query=string',
  pathname: '/path/to/file',
  path: '/path/to/file?query=string',
  href: 'http://user:pass@host.com:8080/path/to/file?query=string#hash' }

PATH

处理本地文件目录需要使用Node.js提供的path模块,它可以方便地构造目录

通过HTTP,URL,FS,PATH

用代码去认识:构造了一个文件系统

"use strict";
var fs = require("fs"),
  url = require("url"),
  path = require("path"),
  http = require("http");

//从命令行参数获取当前线程的root目录,默认目录是当前目录
var root = path.resolve(process.argv[2] || ".");

console.log("static root dir:" + root);

//创建service
var server = http.createServer(function(request, response) {
  //获取URL的path
  var pathname = url.parse(request.url).pathname;
  //获取对应的本地文件路径
  var filepath = path.join(root, pathname);
  //获取文件状态
  fs.stat(filepath, function(err, stats) {
    if (!err && stats.isFile()) {
      // 没错
      console.log("200 " + request.url);
      response.writeHead(200);
      fs.createReadStream(filepath).pipe(response);
    } else {
      // 出错
      console.log("404 " + request.url);
      response.writeHead(404);
      response.end("404 Not Fount");
    }
  });
});

server.listen(8080);
console.log("server is running at http : 8080");

浏览器访问到本地文件:

image-20200225055606779

控制台输出:

static root dir:/Users/shangyifeng/Desktop/js
filePath.js:10
server is running at http : 8080
filePath.js:35
404 /
filePath.js:27
404 /favicon.ico
filePath.js:27
200 /app.js
filePath.js:22
404 /filePa
filePath.js:27
200 /filePath.js
filePath.js:22
200 /app.js

crypto

crypto模块的目的是为了提供通用的加密和哈希算法。用纯JavaScript代码实现这些功能不是不可能,但速度会非常慢。Nodejs用C/C++实现这些算法后,通过cypto这个模块暴露为JavaScript接口,这样用起来方便,运行速度也快。

MD5 && SHA1

const crypto = require('crypto');

const hash = crypto.createHash('md5');
 
// 可任意多次调用update():
hash.update('Hello, world!');
hash.update('Hello, nodejs!');

console.log(hash.digest('hex')); // 7e1977739c748beac0c0fd14fd26a544

官网介绍了很多种语法

https://nodejs.org/dist/latest-v13.x/docs/api/crypto.html

over,暂时就这样

其他API

官网内容最详细,此行的目的仅是为了简单的了解nodejs,方便自己学习Vue这些前端框架。

https://nodejs.org/dist/latest-v13.x/docs/api/

详情内容,以后用到,再查询官网。

2020年02月25日07:40:07

规划了一下自己的学习路线,觉得node暂时认知到这里就这样就行了。

posted @ 2020-02-23 11:48  dawa大娃bigbaby  阅读(239)  评论(0编辑  收藏  举报