node.js 模块化开发

CommonJs

JavaScript 是一个强大面向对象语言,它有很多快速高效的解释器。

然而, JavaScript 标准定义的 API 是为了构建基于浏览器的应用程序。并没有制定一个用于更广泛的应用程序 的标准库

CommonJS 规范的提出,主要是为了弥补当前 JavaScript 没有标准库的缺陷。它的终极目标就是:提供一个类似 Python,Ruby 和 Java 语言的标准库,而不只是让 JavaScript 停留在小脚本程序的阶段。

用 CommonJS API 编写出的应用,不仅可以利用 JavaScript 开发客 户端应用,而且还可以编写以下应用。
•服务器端 JavaScript 应用程序。(nodejs)
•命令行工具。
•桌面图形界面应用程序。

CommonJS 就是模块化的标准,nodejs 就是 CommonJS(模块化)的实现。

Node.js模块化开发

Node 应用由模块组成,采用 CommonJS 模块规范

JS开发弊端

(1)文件与文件直接依赖关系不明确
在这里插入图片描述

(2)命名冲突
在这里插入图片描述

什么是模块化

(1)一个js文件就是一个模块

(2)每个模块都是一个独立的作用域,在这个而文件中定义的变量、函数、对象都是私有的,对其他文件不可见。

模块分类

核心模块(系统模块)
核心模块部分在 Node 源代码的编译过程中,编译进了二进制执行文件。在 Node 进程启动时,部分核心模块就被直接加载进内存中,所以这部分核心模块引入时,文件定位和 编译执行这两个步骤可以省略掉,并且在路径分析中优先判断,所以它的加载速度是最快的。

如:HTTP 模块 、URL 模块、Fs 模块都是 nodejs 内置的核心模块,可以直接引入使用。

第三方模块
由社区或个人提供,需要通过npm安装后使用

自定义模块(文件模块)
文件模块则是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、 速度相比核心模块稍微慢一些,但是用的非常多。这些模块需要我们自己定义。

用户自定义模块

由开发人员创建的模块(JS文件)

基本使用:
1 创建模块
2 引入模块

注意:自定义模块的路径必须以./获取…/开头

// 加载模块
require('./a')     // 推荐使用,省略.js后缀!

require('./a.js')
模块导出与导入

导出exports(exports方法导出)

var obj = {
    
    
    get: function() {
    
    
        console.log(111);
    },
    post: function() {
    
    
        console.log(222);
    }
}
exports.xxxx = obj;

导入require

//此时的request是在request.js中暴露的对象
const request = require("./moudle/request");

console.log(request);

在这里插入图片描述
导出exports(module.exports方法导出)

var obj = {
    
    
    get: function() {
    
    
        console.log(111);
    },
    post: function() {
    
    
        console.log(222);
    }
}
module.exports = obj;

导入require

//此时的request是在request.js中暴露的对象
const request = require("./moudle/request");

console.log(request);

在这里插入图片描述
require()谁,就会执行谁

exports与module.exports

module.exports是模块导出的另一种方式

当exports对象和module.exports对象指向的不是一个对象时,以module.exports为准。此时exports导出不在生效。

如果方法是独立的 建议使用exports

如果所以方法放在一个对象里面 建议使用module.exports

package.json的使用

在node_modules文件夹下的模块index.js文件可以直接引入,见下图:
在这里插入图片描述
此时index.js文件在jxios文件夹下 jxios文件夹在node_modules文件夹下

正常引入文件需要 写全引入路径,比如:

const jxios = require("./node_modules/jxios/index")

jxios.get();

但是因为在node_modules下,所以可以简写:

const jxios = require("index")

jxios.get();

如果在node_modelus下新建模块abcd并新建文件abcd.js,路径如下:
在这里插入图片描述
此时简写引入会不成立:
在这里插入图片描述
因为node.js会默认去寻找node_modules对应模块下的index.js文件,abcd模块下没有index.js文件,所以会报错。

可以用package.json文件解决:
在这里插入图片描述
此时在abcd模块下就有了package.json文件:
在这里插入图片描述
此时简写路径就可以运行:
在这里插入图片描述
因为此时node.js进入abcd模块下首先找到package.json文件 并查看主入口文件:

"main": "abcd.js",

这时abcd.js就相当于index.js,所以可以简写引入。

第三方模块(包)

Nodejs 中除了它自己提供的核心模块外,我们可以自定义模块,也可以使用第三方的 模块。Nodejs 中第三方模块由包组成,可以通过包来对一组具有相互依赖关系的模块进行统一管理。

完全符合 CommonJs 规范的包目录一般包含如下这些文件:
package.json :包描述文件。
• bin :用于存放可执行二进制文件的目录。
• lib :用于存放 JavaScript 代码的目录。
• doc :用于存放文档的目录。

在 NodeJs 中通过 NPM 命令来下载第三方的模块(包):
npm(node package manager): node的第三方模块管理工具

下载:npm install 模块名称
在这里插入图片描述
下载到地方:npm自动创建一个文件夹便于存储,下载到命令行目录下
在这里插入图片描述
6.删除模块: npm uninstall 模块名称
在这里插入图片描述
在这里插入图片描述
本地安装:安装的当前项目中(库文件)

全局安装:安装到公共地方,项目都可使用(命令行工具)

npm介绍

npm 是世界上最大的开放源代码的生态系统

我们可以通过 npm 下载各种各样的包, 这些源代码(包)我们可以在 https://www.npmjs.com 找到。

npm 是随同 NodeJS 一起安装的包管理工具,能解决 NodeJS 代码部署上的很多问题, 常见的使用场景有以下几种:

1.允许用户从 NPM 服务器下载别人编写的第三方包到本地使用。(silly-datetime)

2.允许用户从 NPM 服务器下载并安装别人编写的命令行程序(工具)到本地使用。 (supervisor)

3.允许用户将自己编写的包或命令行程序上传到 NPM 服务器供别人使用。

npm 命令详解
npm -v 

查看 npm 版本

npm install Module Name 

使用 npm 命令安装模块
如安装 jq 模块:npm install jquery

npm uninstall moudleName 

卸载模块

npm list 

查看当前目录下已安装的 node 包

npm info 模块

查看模块的版本

npm install [email protected]

指定版本安装

package.json文件

package.json定义了这个项目所需要的各种模块,以及项目的配置信息(比如名称、版本、 许可证等元数据)
1、创建 package.json
npm init 或者 npm init –yes

2、package.json 文件

{
    
    
    "name": "test",
    "version": "1.0.0",
    "description": "test",
    "main": "main.js",
    "keywords": ["test"],
    "author": "wade",
    "license": "MIT",
    "dependencies": {
    
     "express": "^4.10.1" },
    "devDependencies": {
    
    
        "jslint": "^0.6.5"
    }
}

3、安装模块并把模块写入 package.json(依赖)

npm install babel-cli --save-dev 

npm install 模块 --save 

npm install 模块 --save-dev

4、dependencies 与 devDependencies 之间的区别
–save-dev 和 –save 的区别
我们在使用npm install 安装模块或插件的时候,有两种命令把他们写入到 package.json 文件里面去,比如:

–save-dev 安装的 插件,被写入到 devDependencies 对象里面去
–save 安装的 插件 ,被写入到 dependencies 对象里面去

package.json 文件里面的 devDependencies 和 dependencies 对象区别呢
devDependencies 里面的插件只用于开发环境,不用于生产环境
dependencies 是需要发布到生产环境的。

假如用angularjs框架开发一个程序,开发阶段需要用到gulp来构建你的开发和本地运行环境。angularjs一定要放到dependencies里,因为以后程序到生产环境也要用。gulp则是你用来压缩代码,打包等需要的工具,程序实际运行的时候并不需要,所以放到devDependencies里就ok了。

"dependencies": {
    
    
    "ejs": "^2.3.4",
    "express": "^4.13.3",
    "formidable": "^1.0.17"
}

^表示第一位版本号不变,后面两位取最新的
~表示前两位不变,最后一个取最新
*表示全部取最新
去掉前面符号:

"express": "4.13.3",

在下载多少次版本也不会变

淘宝镜像

淘宝 NPM 镜像是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10 分钟 一次以保证尽量与官方服务同步。

我们可以使用我们定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:

npm install -g cnpm --registry=https://registry.npm.taobao.org
nrm

nrm(npm registry manager): npm下载地址切换工具

npm默认在国外,国内下载慢

步骤:
(1)npm install nrm -g
(2)查询下载地址 nrm ls
(3)切换npm下载地址 nrm use 下载地址名称
在这里插入图片描述
在这里插入图片描述
gulp模块挺大的,所以切换以后速度还是非常快的。

核心模块(系统模块)

fs模块
fs.stat 检测是文件还是目录
const fs = require("fs");
fs.stat('package.json', (err, data) => {
    
    
    if (err) {
    
    
        console.log(err);
    }

    console.log(`文件:${
      
      data.isFile()}`);
    console.log(`文件:${
      
      data.isDirectory()}`);
})

在这里插入图片描述

fs.mkdir 创建目录
const fs = require("fs");

// path将创建的目录路径
// mode目录权限( 读写权限) 默认777
// callback 回调, 传递异常参数err

fs.mkdir('css', (err) => {
    
    
    if (err) {
    
    
        console.log(err);
        return;
    }

    console.log('创建成功');
})

在这里插入图片描述

fs.writeFile 创建写入文件
const fs = require("fs");
/*
filename(String)  文件名称
data (String/Buffer)  将要写入的内容,可以是字符串,可以是buffer数据
options  (Object)  option数组对象,包含:
    encoding (String)  可选值 默认'utf-8'  
    mode (Number)  文件读写权限,默认值438
    flag (String)  默认值'w'
callback  {Function}  回调,传递一个异常参数err
*/

fs.writeFile('./css/index.css', '你好eqeqeqeqe', (err) => {
    
    
    if (err) {
    
    
        console.log(err);
    }

    console.log('写入文件成功 ');
})

在这里插入图片描述
此时再写入新的 会覆盖原有写入的内容

fs.appendFile 追加文件
const fs = require("fs");

fs.appendFile('./css/base.css', 'h2{color:red}', (err) => {
    
    

    if (err) {
    
    
        console.log(err);
        return;
    }
    console.log('appendFile 成功');

})

在这里插入图片描述
追加文件写入新的不会覆盖原有内容,会在原有内容后写入新内容

fs.readFile 读取文件
const fs = require("fs");
fs.readFile('./css/base.css', (err, data) => {
    
    
    if (err) {
    
    
        console.log(err);
        return;
    }
    console.log(data);
    console.log(data.toString()); //把Buffer 转化成string类型
})

在这里插入图片描述

fs.readdir 读取目录
const fs = require("fs");
fs.readdir('./css', (err, data) => {
    
    

    if (err) {
    
    
        console.log(err);
        return;
    }

    console.log(data);
})

在这里插入图片描述

fs.rename 重命名
const fs = require("fs");
// 7.fs.rename 重命名   
//功能: 1、 表示重命名 2、 移动文件
fs.rename('./css/index.css', './css/base.css', (err) => {
    
     //把css目录下index.css文件重命名为base.css

    if (err) {
    
    
        console.log(err);
        return;
    }

    console.log('重命名成功');

})

fs.rename('./css/base.css', './html/base.css', (err) => {
    
     //把css目录下base.css文件 移动到html目录下

    if (err) {
    
    
        console.log(err);
        return;
    }
    console.log('移动文件成功');

})

在这里插入图片描述

fs.rmdir 删除目录
const fs = require("fs");
fs.rmdir('./css', (err) => {
    
     //删除css目录
    if (err) {
    
    
        console.log(err);
        return;
    }
    console.log('删除目录成功');
})
fs.unlink 删除文件
const fs = require("fs");
fs.unlink('./html/index.css', (err) => {
    
    
    if (err) {
    
    
        console.log(err);
        return;
    }
    console.log('删除文件成功');
})
fa模块练习

1.判断服务器上面有没有upload目录。如果没有创建这个目录,如果有的话不做操作。 (图片上传)

const fs=require('fs');
var path='./upload';

fs.stat(path,(err,data)=>{
    
    
    if(err){
    
    
        //执行创建目录
        mkdir(path);
        return;
    }
    if(!data.isDirectory()){
    
    
         //首先删除文件,再去执行创建目录
         fs.unlink(path,(err)=>{
    
    
            if(!err){
    
    
                mkdir(path);
            }else{
    
    
                console.log('请检测传入的数据是否正确');
            }
        })
    }
})

//创建目录的方法
function mkdir(dir){
    
    
    fs.mkdir(dir,(err)=>{
    
    
        if(err){
    
    
            console.log(err);
            return;
        }
    });
}

mkdirp模块 快速实现

/*
1、https://www.npmjs.com/package/mkdirp

2、cnpm i mkdirp --save  /  npm i mkdirp --save 

3、var mkdirp = require('mkdirp');

4、看文档使用

*/ 

var mkdirp = require('mkdirp');

// mkdirp('./upload', function (err) {
    
    
//     if (err) {
    
    
//         console.error(err);
//     }    
// });




// mkdirp('./uploadDir');




mkdirp('./upload/aaa/xxxx', function (err) {
    
    
    if (err) {
    
    
        console.error(err);
    }    
});

2.wwwroot文件夹下面有images css js 以及index.html , 找出 wwwroot目录下面的所有的目录,然后放在一个数组中
1.改造for循环 递归实现:

const fs=require('fs');

//这是错误的写法  注意:fs里面的方法是异步

    var path='./wwwroot';
    var dirArr=[];
    fs.readdir(path,(err,data)=>{
    
    
        if(err){
    
    
            console.log(err);
            return;
        }    
        for(var i=0;i<data.length;i++){
    
     //for循环先执行完 i=4  不存在data[4]这个数据
            fs.stat(path+'/'+data[i],(error,stats)=>{
    
    
                if(stats.isDirectory()){
    
    
                    dirArr.push(data[i]);
                }
            })
        }
        console.log(dirArr);//打印结果为空 {}
    })
    console.log(dirArr);  //打印结果为空 {}
    
	//所以这是错误的写法  忽略了node.js异步



//定时器 异步例子
    
        for(var i=0;i<3;i++){
    
     
        //for循环先执行完 i=3 
        //然后执行定时器打印3个3
            setTimeout(function(){
    
    
                console.log(i);
            },100)
        }
    




//1、改造for循环  递归实现      
//2、nodejs里面的新特性  async await


var path='./wwwroot';
var dirArr=[];
fs.readdir(path,(err,data)=>{
    
    
    if(err){
    
    
        console.log(err);
        return;
    }    
    (function getDir(i){
    
    
        if(i==data.length){
    
     //执行完成
            console.log(dirArr);
            return;
        }
        fs.stat(path+'/'+data[i],(error,stats)=>{
    
    
            if(stats.isDirectory()){
    
    
                dirArr.push(data[i]);
            }
            getDir(i+1)
        })
    })(0)
})
读取流

fs.createReadStream 从文件流中读取数据

const fs = require('fs');
// 创建一个可读流
var readStream = fs.createReadStream('./data/input.txt');

var count = 0;
var str = '';

readStream.on('data', (data) => {
    
    
    str += data;
    count++;
})

readStream.on('end', (data) => {
    
    
    console.log(str);
    console.log(count);
})

readStream.on('err', (data) => {
    
    
    console.log(err);
})
写入流

fs.createWriteStream 写入文件

const fs = require('fs');
var str = '';
for (var i = 0; i < 20; i++) {
    
    
    str += 'cnmcnmcnmCNM\n'
}
// 创建一个可写流
var writeStream = fs.createWriteStream('./data/output.txt')

writeStream.write(str);
//标记文件末尾
writeStream.end();

writeStream.on('finish', () => {
    
    
    console.log('写入完成');
})
管道流

管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传 递到另外一个流中。

const fs = require('fs');
// 创建一个可读流
var readStream = fs.createReadStream('./88.png');
// 创建一个可写流
var writeStream = fs.createWriteStream('./data/99.png')
// 管道读写操作 
// 读取 88.png ,并将内容写入到 data目录下99.png 
readStream.pipe(writeStream);
async/await

async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理解 async 用于申明一个异步的 function ,而 await 用于等待一个异步方法执行完成。

async 是让方法变成异步,在终端里用 node 执行这段代码,你会发现输出了 Promise {‘Hello async’ },这时候会发现它返回的是 Promise。

function test1() {
    
    
    return '123'
}
const test3 = test1();
console.log(test3); //123


async function test2() {
    
    
    return '456'
}
const test4 = test2();
console.log(test4); //Promise { '456' }

await 在等待 async 方法执行完毕,其实 await 等待的只是一个表达式,这个表达式在官方 文档里说的是 Promise 对象,但是它也可以接受普通值。

注意:await 必须在 async 方法中 才可以使用,因为 await 访问本身就会造成程序停止堵塞,所以必须在异步方法中才可以使用。

function getData() {
    
    
    return 'zhangsan';
}

async function testAsync() {
    
    
    return 'Hello async';
}

async function test() {
    
    
    const v1 = await getData();
    const v2 = await testAsync();
    console.log(v1, v2); //zhangsan Hello async
}
test();

async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而 await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。

function findData() {
    
    
    return new Promise(resolve => {
    
    
        setTimeout(() =>
            resolve("long_time_value"), 1000);
    });
}

async function test() {
    
    
    const v = await findData();
    console.log(v); //long_time_value
}
test();

async-await-Promise

猜你喜欢

转载自blog.csdn.net/Ulrica_Amaris/article/details/110496395