一文入门NodeJS

文章汇总:https://www.cnblogs.com/dotnetcrazy/p/9160514.html 目录: 1.环境配置¶ 1.1.NPM国内镜像¶ 1.2.VSCode调试¶ 1.3.Jupyter NoteBook¶ 2.常用模块¶ 2.1.http(常用)¶ 2.2.fs(常用)¶ 2.3.url(常用)¶ 2.4.zlib(常用)¶ 2.5.path¶ 2.6.crypto¶ 2.7.os¶ 2.8.多进程¶ 2.9.uuid¶ NodeJS 1.环境配置 之前讲ES6的时候有提过一部分Node的知识,简单回顾下:一文读懂ES6 1.1.NPM国内镜像 npm国内镜像:https://npm.taobao.org 配置国内源:npm install -g cnpm --registry=https://registry.npm.taobao.org 然后就可以把cnpm当作npm来用了,比如之前的React组件案例: cnpm install react cnpm install react-dom cnpm i babel-core@old 卸载安装的包:npm uninstall -g uuid用npm而不是cnpm 常用参数说明: i是install的简写 -g是安装到全局环境中(默认是当前目录) -D添加为开发依赖(-D ==> --save-dev 开发环境) -S添加为生产依赖(-S ==> --save 生产环境) eg:cnpm i express -S eg:cnpm init之后: 1.init.png1.add.png PS:你把依赖包删了也没事,执行cnpm i就会会根据package.json自动安装依赖包 课外阅读: npm如何管理依赖包的版本 https://www.jianshu.com/p/1470c5d7b8c3 禁止npm自动升级依赖包以及所有下级依赖包版本的方法 https://www.jianshu.com/p/f481cf9b0817 1.2.VSCode调试 这个之前也说过,可以看看:VSCode and NoteBook for JavaScript | NodeJS,简单说下: 每次F5运行的时候选一下NodeJS,或者添加一下调试的配置文件 { "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "启动程序", "program": "${workspaceFolder}/${relativeFile}" } ] } nodejs用法和js基本一样,只是多了些服务器的模块,eg: 1.vscode.png 配置NodeJS和HTML 如果想同时运行nodejs和html再添加下配置就行了,比如: { "version": "0.2.0", "configurations": [ { "type": "chrome", "request": "launch", "name": "Launch Chrome against localhost", "url": "http://localhost:8080/${relativeFile}", "webRoot": "${workspaceFolder}" }, { "type": "node", "request": "launch", "name": "启动程序", "program": "${workspaceFolder}/${relativeFile}" } ] } 配置完成后:想运行HTML就选择谷歌浏览器 1.浏览器.png 想运行nodejs的js文件就选择启动程序(现在运行JS文件的时候,F5即可自动切换成node) 1.nodejs.png 配置说明 ${workspaceRoot} VS Code当前打开的文件夹 ${file} 当前打开的文件 ${relativeFile} 相对于workspaceRoot的相对路径 ${fileBasename} 当前打开文件的文件名 ${fileDirname} 所在的文件夹,是绝对路径 ${fileExtname} 当前打开文件的扩展名 1.3.Jupyter NoteBook ijavascript依赖于Python2.7,详细过程:Jupyter NoteBook IJavaScript 配置 # 如果nodejs和npm没安装可以先安装下 sudo apt-get install nodejs npm # 把ijavascript安装到全局环境中 sudo npm install -g ijavascript # 安装 ijsinstall 然后就和Python一样用了: 1.ijavascript.png 2.常用模块 这块官方文档写的很详细,我就简单说说,后面用到再详细说 中文文档:http://nodejs.cn/api 官方文档:https://nodejs.org/api 2.1.http(常用) 文档:http://nodejs.cn/api/http.html or https://nodejs.org/api/http.html NodeJS既然作为服务器,那得先有个服务器的样子,我们来个简单的案例: node // ES6语法:import http from "http"; (现在还没能完全支持) const http = require("http") // 创建一个服务器 let server = http.createServer((request, response) => { // 每次请求都会执行这个方法 console.log(request.url); response.write("

Test NodeJS"); response.end() // 告诉浏览器响应结束 }); // 服务器启动并监听指定端口 server.listen(8080); // 这个和其他语言不一样,直接监听对应的端口 效果: 1.vscode.png 其他内容需要结合其他模块一起讲解 2.2.fs(常用) 文档:http://nodejs.cn/api/fs.html or https://nodejs.org/api/fs.html 这个是IO对应的模块,推荐使用异步方法,简单看看:(xxxFileSync是同步方式,不建议使用) const fs = require("fs"); // 文件读取 fs.readFile("test.txt",(ex,data) => { // 如果文件不存在就输出错误信息 if(ex){ console.log(ex); }else{ console.log(data.toString()); } }); console.log("[ReadFile异步验证]我出现就是异步"); [ReadFile异步验证]我出现就是异步 { Error: ENOENT: no such file or directory, open 'test.txt' errno: -2, code: 'ENOENT', syscall: 'open', path: 'test.txt' } // 创建一个文件 fs.writeFile("test.txt","文本内容",ex => { if(ex){ // 出错就输出info console.log(ex); } }); console.log("[WriteFile异步验证]我出现就是异步"); [WriteFile异步验证]我出现就是异步 // 文件追加 fs.appendFile("test.txt","追加内容",ex => { if(ex){ // 出错就输出info console.log(ex); } }); console.log("[AppendFile异步验证]我出现就是异步"); [AppendFile异步验证]我出现就是异步 // 现在再读着看看 fs.readFile("test.txt",(ex,data) => { // 如果文件不存在就输出错误信息 if(ex){ console.log(ex); }else{ console.log(data.toString()); } }); 文本内容追加内容 PS:如果文件不是文本文件,就不能toString了(data默认是buffer类型) node fs.readFile("知识星球.png", (ex, data) => { if (ex) { console.log("读取错误:", ex); } else { console.log(data); // 看看buffer是啥样的 fs.writeFile("test.png", data, ex => { if (ex) { console.log("复制错误:", ex); } }); } }); 效果: 图片照常打开: 公众号:逸鹏说道 简单小结一下: 读取文件:fs.readFile("xxx", (ex, data) => { }); 创建文件:fs.writeFile("xxx", data, ex => {}); 追加文件:fs.appendFile("xxx", data, ex => {}); data是buffer类型,内置了: toString():buffer转换成字符串 toJSON():buffer转化成Json // 看个案例 data = { "name": "小明", "age": "23" }; fs.writeFile("to.txt", data, ex => { if (ex) { console.log(ex); } }); fs.readFile("to.txt", (ex, data) => { if (ex) { console.log(ex); } else { console.log(data); console.log(data.toJSON()); console.log(data.toString()); console.log(data.toLocaleString()); } }); { type: 'Buffer', data: [ 91, 111, 98, 106, 101, 99, 116, 32, 79, 98, 106, 101, 99, 116, 93 ] } [object Object] [object Object] 注意点 上面几个方法(eg:readFile)都是先把数据都缓存到内存中,然后才回调,这样比较浪费内存,对于大文件不友好,so ==> 流走起 Stream(常用) 用法比较简单,看个案例: node const fs = require("fs"); let rs = fs.createReadStream("知识星球.png"); let ws = fs.createWriteStream("test.png"); // 可以这么理解,rs是水龙头防水的地方,写反了也就出不了水了 rs.pipe(ws); // 创建一个管道,流从r端到w端 还有一些类似于监听的事件: node const fs = require("fs"); let rs = fs.createReadStream("知识星球.png"); let ws = fs.createWriteStream("test.png"); rs.pipe(ws); // 创建一个管道,流从r端到w端 // 可以理解为错误触发的事件 rs.on("error", ex => { console.log("读取失败", ex); }); rs.on("end", () => { console.log("读取完成"); }); ws.on("error", ex => { console.log("写入失败", ex); }); // 注意,写入流完成不叫end ws.on("finish", () => { console.log("写入完成"); }); 2.3.url(常用) 文档:http://nodejs.cn/api/url.html or https://nodejs.org/api/url.html 说url模块之前得先说下querystring模块 1.querystring 文档:http://nodejs.cn/api/querystring.html or https://nodejs.org/api/querystring.html 这个是专门针对参数进行解析的,来个案例: const querystring = require("querystring"); let jd_qs = "keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2"; // 咋一看,好像挺方便,但是有坑:看下一个demo let str = querystring.parse(jd_qs); console.log(str) { keyword: '空气净化器', enc: 'utf-8', qrst: '1', rt: '1', stop: '1', vt: '2', psort: '3', stock: '1', wtype: '1', cod: '1', click: '2' } // 用户请求一般都是类似于这样的 let jd_url = "https://search.jd.com/Search?keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2"; // querystring.parse 只是对?后面(不包括`?`)的参数进行解析(以`=`和`&`分隔) str = querystring.parse(jd_url); console.log(str); { 'https://search.jd.com/Search?keyword': '空气净化器', enc: 'utf-8', qrst: '1', rt: '1', stop: '1', vt: '2', psort: '3', stock: '1', wtype: '1', cod: '1', click: '2' } 注意:querystring.parse 只是对?后面(不包括?)的参数进行解析(以=和&分隔) 2.url 上面说下querystring只是一个铺垫,基本上不太用,url模块已经包含这个了: const url = require("url"); // port=null说明是默认端口(http:80,https:443) let jd_url = "https://search.jd.com/Search?keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2"; let str = url.parse(jd_url); console.log(str); // 发现query并没有解析 Url { protocol: 'https:', slashes: true, auth: null, host: 'search.jd.com', port: null, hostname: 'search.jd.com', hash: null, search: '?keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2', query: 'keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2', pathname: '/Search', path: '/Search?keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2', href: 'https://search.jd.com/Search?keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2' } // 想要解析`query`,可以多传一个参数 str = url.parse(jd_url, true); console.log(str); // 对query解析 Url { protocol: 'https:', slashes: true, auth: null, host: 'search.jd.com', port: null, hostname: 'search.jd.com', hash: null, search: '?keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2', query: { keyword: '空气净化器', enc: 'utf-8', qrst: '1', rt: '1', stop: '1', vt: '2', psort: '3', stock: '1', wtype: '1', cod: '1', click: '2' }, pathname: '/Search', path: '/Search?keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2', href: 'https://search.jd.com/Search?keyword=空气净化器&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort=3&stock=1&wtype=1&cod=1&click=2' } PS:一般都是这么用的: node // {a, b} = {a:21,b=34,c=22} 只要对应即可解包,如果想取别名可以使用:{a:xx, b} = {...} let { pathname, query } = url.parse(request.url, true); 3.前几个模块的综合案例 结合上面的HTTP模块,来个简单的web服务器: node const fs = require("fs"); const url = require("url"); const http = require("http"); // 创建服务 let server = http.createServer((request, response) => { // 请求 // {a, b} = {a:21,b=34,c=22} 只要对应即可解包,如果想取别名可以使用:{a:xx, b} = {...} let { pathname, query } = url.parse(request.url, true); console.log(query, pathname); // 读取对应文件 fs.readFile(`www${pathname}`, (ex, data) => { if (ex) { // 返回404状态码,并设置编码为UTF-8 response.writeHeader(404, { "Content-Type": "text/html;charset=utf-8" }); // 提示需要在 writeHeader 之后,不然访问的是浏览器404页面 response.write("

访问的页面不存在~

"); } else { response.write(data); } // 响应结束 response.end(); }); }); // 服务器启动并监听指定端口 server.listen(8080); 输出:(www目录就两个文件,一个test.html,一个test.png) 2.nodejs.png 推荐写法: node const fs = require("fs"); const url = require("url"); const http = require("http"); let server = http.createServer((request, response) => { let { pathname } = url.parse(request.url, true); console.log(pathname); let rs = fs.createReadStream(`www${pathname}`); // `request`和`response`就是一个典型的读写流(`ReadStream`、`WriteStream`) rs.pipe(response); // 读取失败 ==> 404 rs.on("error", ex => { response.writeHeader(404); response.write("404 Not Found"); response.end(); }); }); server.listen(8080); PS:request和response就是一个典型的读写流(ReadStream、WriteStream) 2.4.zlib(常用) 文档:http://nodejs.cn/api/zlib.html or https://nodejs.org/api/zlib.html 先看个案例:(zlib是读写流) node const fs = require("fs"); const zlib = require("zlib"); // 读写流 let gz = zlib.createGzip(); // 读流 let rs =fs.createReadStream("./www/jquery-2.1.1.js"); // 写流 let ws =fs.createWriteStream("test.js.gz"); // 可以这么理解:(gz是读写流) // rs水龙头先传给了gz,gz又当一个水龙头传给了ws rs.pipe(gz).pipe(ws); ws.on("finish",()=>{ console.log("写入完毕"); }); 效果: 1.zlib.png 静态服务器 结合上面再来个加强版: node const fs = require("fs"); const zlib = require("zlib"); const http = require("http"); let server = http.createServer((request, response) => { // let { pathname } = url.parse(request.url); console.log(request.url); let rs = fs.createReadStream(`www${request.url}`); let gz = zlib.createGzip(); // 响应之前告诉浏览器是gzip的格式 response.setHeader("Content-Encoding", "gzip"); // 返回gzip压缩后的文件 rs.pipe(gz).pipe(response); // 读取失败,404错误 rs.on("error", ex => { response.removeHeader("Content-Encoding"); // 返回404状态码,并设置编码为UTF-8 response.writeHeader(404, { "Content-Type": "text/html;charset=utf-8" }); // 提示需要在 writeHeader 之后,不然访问的是浏览器404页面 response.write("

您访问的页面不存在~

"); response.end(); }); }); server.listen(8080, () => { console.log("服务器启动成功,端口:8080"); }); 输出对比: 1.zlib2.png 2.5.path 文档:http://nodejs.cn/api/path.html or https://nodejs.org/api/path.html 这个主要是针对路径的模块,看个案例:path.parse() const path = require("path"); let file_name = "./images/png/小明.png"; // 文件路径 ./images/png console.log(path.dirname(file_name)); // 提取出用 `/` 隔开的 `path` 的最后一部分 // 小明.png console.log(path.basename(file_name)); // 文件后缀 .png console.log(path.extname(file_name)); // 文件信息 {root: "", dir: "./images/png", base: "小明.png", ext: ".png", name: "小明"} console.log(path.parse(file_name)); // 这个经常使用 // ------------------------------ // 当前文件所在文件夹绝对路径 console.log(path.resolve()); // 文件的绝对路径 console.log(path.resolve(file_name)); ./images/png 小明.png .png { root: '', dir: './images/png', base: '小明.png', ext: '.png', name: '小明' } /home/dnt/桌面/work/BaseCode/javascript/NoteBook/2.Node /home/dnt/桌面/work/BaseCode/javascript/NoteBook/2.Node/images/png/小明.png // 可以看看path的完整信息 console.log(path); { resolve: [Function: resolve], normalize: [Function: normalize], isAbsolute: [Function: isAbsolute], join: [Function: join], relative: [Function: relative], _makeLong: [Function: _makeLong], dirname: [Function: dirname], basename: [Function: basename], extname: [Function: extname], format: [Function: format], parse: [Function: parse], sep: '/', delimiter: ':', win32: { resolve: [Function: resolve], normalize: [Function: normalize], isAbsolute: [Function: isAbsolute], join: [Function: join], relative: [Function: relative], _makeLong: [Function: _makeLong], dirname: [Function: dirname], basename: [Function: basename], extname: [Function:

50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信