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文件,代码如下
Copy
//创建 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. 创建代码,认识模块的调用

    Copy
    '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 }

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

    Copy
    '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不同。

Copy
> 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进程。

Copy
> 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. 异步读文件

    Copy
    '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后缀,并且不接收回调函数,函数直接返回结果。

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

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

    Copy
    '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()

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

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

    Copy
    '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

    Copy
    '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. 读流 ()

    Copy
    '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. 写流 ()

    Copy
    '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 ()

    Copy
    '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服务器程序

    Copy
    '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对象.

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

//解析结果如下

Copy
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#

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

Copy
"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

控制台输出:

Copy
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#

Copy
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 @   dawa大娃bigbaby  阅读(246)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示
CONTENTS