Node.js基础笔记

1:模块系统

JS这门语言最开始是作为浏览器脚本存在的,本身并没有模块系统,模块的划分靠html中的script标签控制,然而node.js将js作为后台开发语言,必须要有模块划分,如果一个文件要将本文件定义的变量和函数暴露出去,可以使用export:

//文件a.js
let a = 10;
function f(){};
module.exports = {
	a:a,
	f:f
}

或者

module.exports.a = a;
module.exports.f = f;

如果不涉及函数和数组,直接使用export也可,因此下面这种写法也是可以的

exports.a = a;	//a不是数组和函数,可以省略module关键字
module.exports.f = f;

node中模块的实现,本质是将文件包含在了一个函数里,上面文件中的代码编译后会用函数进行包装,转化为下面这种形式,并预先生成module对象,作为参数传入。

module={
	id:'a.hs',
	exports:{}
}
function load(module){
	let a = 10;
	function f(){};
	return module.exports;
}

如果要使用上面的模块,则需要用到require关键字:

const a = require('./a.js');
console.log(a.a);
a.f();

这是用require导入自定义模块的情况,如果需要使用系统模块,比如文件系统,则不需要添加 ./ 表明在当前目录内:

const fs = require('fs');

在es6之后有了和其他语言一样的import关键字,import是编译时调用,require是运行时调用,因而可以放在文件的任何一个位置(这里其实有个疑惑,import难道不能放在文件的任何一个位置么?)。

2:文件系统

一共分为读、写、文件状态获取、读流、写流、pipe几个部分。
读文件:

const fs = require('fs');
//异步读取
//如果是二进制数据,或者没有指定解析格式为utf-8,则会返回Buffer对象,本质是一个数组,数组中的每个元素是16进制值。
fs.read('文件路径','utf-8',function (err,data) {
    if(err){
		console.log(err);
	}else{
		console.log(data);
	}
});
//同步读取
try {
    let data =fs.readFileSync('文件路径','utf-8');
}catch (e) {
    console.log(e)
}
//string和buffer之间相互转化
let data2 = Buffer.from(data,'utf-8');	//将字符串转化为二进制
data = data2.toString('utf-8');

写文件

//同步写入
fs.write('文件路径','utf-8',function (err) {
    console.log(err);
});
//异步写入
try {
    fs.writeFileSync('文件路径','utf-8');    
}catch(e){
    console.log(e);
};

readStream

如果文件很大,不可能一次性从磁盘读取到内存中,这个时候就需要使用流的方式每次读一部分。流是一种抽象,就好像从自来水管接一桶水一样。

const rs = fs.createReadStream('文件路径','utf-8');
re.on('data',function (chunk) {});	//读取一段文件
re.on('end',function () {});	//文件读取完毕
re.on('error',function (err) {});	//文件读取出错

writeStream

const ws = fs.createWriteStream('');
ws.write('','utf-8');
ws.write('','utf-8');
ws.end();

pipe

pipe表示管道,如果需要把一个文件的内容读出来,然后写入另一个文件中,就好像在两个文件中建立了一根水管一样,所以叫管道。
过程:使用读流从文件A中读取数据,使用写流将读取的数据写入文件B中

const fs = require('fs');
const rs = fs.createReadStream('文件A','utf-8');
const ws = ts.createWriteStream('文件B');
rs.pipe(ws);

3:http

服务器自然离不开网络,这部分用于接收和响应http请求。
最简单的http服务器:

const http = require('http');
//创建服务器
//这里res对象本质是一个writeStream
const server = http.createServer(function (req,res) {
    console.log(req.method);
    console.log(req.url);
    res.writeHead(200,{
        'Content-Type':'text-html'
    });
    res.end('<h1>hello world</h1>');
});
server.listen(8080);

文件服务器:

const
    fs = require('fs');
    url =require('url');
    path = require('path');
    http = require('http');

//||符号:如果左边表达式为真返回左边表达式,否则返回右边表达式,这里如果行命令启动的时候指定了文件路径,那么使用行命令指定的文件路径,否则使用当前代码文件所在的根目录为文件目录 path.resolve('.') 即是获取当前跟目录
const root = path.resolve(process.argv[2] || '.');
const server = http.createServer(function (req,res) {
	
	//获取浏览器中输入的文件路径,这里的路径不包含host和端口因而不需要特殊处理
    const pathname = req.url;
    const filePath = path.join(root,pathname);

	//判断文件是否存在
    fs.stat(filePath,function (err,stat) {
        if (err){
            res.writeHead('404');
            res.end('404 not find');
        }else{
            res.writeHead('200');
            const rs = fs.createReadStream(filePath,'utf-8').pipe(res);
        }
    });
});
server.listen(8080);
console.log('http://127.0.0.1:8080');

4:加密和哈希 —— crypto

hash: 用户验证文件的正确性,同样的文件生成和哈希值是相同的,如果哈希值不同,那么文件肯定也不一样,因而可以用于校验文件的完整性和正确性,hash算法有许多,常用的如MD5、SHA1、SHA256、SHA512等。
MD5:

const crypto = require('crypto');
const md5 = crypto.createHash('md5');

//输入用户MD5加密的内容,这里可以更新多次
md5.update('hello');
md5.update('world');

//使用16进制(hex)输出
console.log(md5.digest('hex'));

Hmac:
Hmac基于MD5、SHA等哈希算法,区别在于Hmac多了一个秘钥,相同的内容如果秘钥不同,生成的哈希也不一样。

const crypto = require('crypto');

//第二个参数即是秘钥
const hmac= crypto.createHmac('md5','goldfish');
hmac.update('hello');
hmac.update('word');
console.log(hmac.digest('hex'));

对称加密aes

let crypto = require('crypto');

function aesEncrypt(data, key, iv) {
	//生成加密器,算法为aes192,秘钥为key,初始向量为iv
	//只有key和iv都相同,生成的密文才是相同得1
    let cipher = crypto.createCipheriv('aes192', key, iv);

	//
    let crypted = cipher.update(data,'utf-8','hex');
    crypted += cipher.final('hex');
    return crypted;
}

function aesDecrypt(encrypt, key, iv) {
    let decipher = crypto.createDecipheriv('aes192', key, iv);
    let decryped = decipher.update(encrypt,'hex','utf-8');
    decryped += decipher.final('utf-8');
    return decryped;
}

还有一些加密api用到的时候再查

5. web开发 —— KOA2

之前nodejs的web框架为express,但由于express存在callback hell的问题,因此这从KOA2开始学起。
node.js可以使用package.json文件管理包依赖,在js目录下新建该文件,写入如下内容:

{
    "name": "hello",
    "version": "1.0.0",
    "description": "Hello Koa 2 example with async",
    "main": "app.js",
    "scripts": {
        "start": "node app.js"
    },
    "keywords": [
        "koa",
        "async"
    ],
    "author": "Tang He",
    "license": "Apache-2.0",
    "repository": {
        "type": "git",
        "url": ""
    },
    "dependencies": {
        "koa": "2.0.0"
    }
}

然后同样在js目录下输入npm install即可,这种方式在管理多个包的时候更为方便,其实主要就是最后的dependencies。
使用koa2新建一个简单的web服务器:

const koa = require('koa');
const app = new koa();

//async 表示这里使用的是一个异步函数
app.use(async function (ctx, next) {
	//调用下一个async函数
    await next();
    ctx.response.type = 'text/html';
    ctx.response.body = '<h1>hello koa</h1>';
});

app.listen(3000);

koa把很多async函数组成一个处理链,每个async函数都可以做一些自己的事情,然后用await next()来调用下一个async函数。我们把每个async函数称为middleware,这些middleware可以组合起来,完成很多有用的功能,看下面的例子。

const koa = require('koa');
const app = new koa();

app.use(async function(context,next) {
    console.log(context.request.url+context.request.method);
    await next();
});

app.use(async function(context, next) {
   const timeBefore = new Date().getTime();
   await next();
   const timeAfter = new Date().getTime();
   console.log(timeAfter-timeBefore);
});
app.use(async function(context, next) {
    await next();
    context.response.type = 'text/html';
    context.response.body = 'hello koa';
});
app.listen(8000);

这里有三个use,先调用第一个use,在该use中调用next()拿到第二个use,同样在第二个use中调用next拿到第三个。如果第二个或者第一个use中的next没有被调用,后面的代码就不会被执行。

koa-router:
提供了路由相关功能,这里路由的实现其实和iOS中的路由框架很像,如果根据用户的请求路径一个个比较效率很低,底层使用哈希表或者二叉查找树就会简单许多,这里koa-router就提供了路由查找的功能。

const koa = require('koa');
const router = require('koa-router')();
const app = new koa();

//接收到请求后打印请求内容,然后转发给下一个use
app.use(async function(context,next) {
    console.log(context.request.url+context.request.method);
    await next();
});

//将请求转发给路由,路由会选择接收请求的处理函数
app.use(router.routes());

router.get('/',function (context,next) {
    context.response.body = '<h1>hello world</h1>'
});

router.get('/goldfish',function (context,next) {
    context.response.body = '<h1>hello goldfish</h1>';
});

app.listen(8000);

koa-bodyparser
上面的代码只能用户处理get请求,如果是post请求呢?请求内容在请求体重,无论是node原生还是koa-router都没有提供body解析的功能,这时候就需要一个解析工具 —— koa-bodyparse:

const koa = require('koa');
const bodyParse = require('koa-bodyparser');
const router = require('koa-router')();

const app = new koa();

app.use(async function(context,next) {
    console.log(context.request.url+context.request.method);
    await next();
});

//请求先被转发到body解析
app.use(bodyParse());

//解析后的请求被转发给路由处理
app.use(router.routes());

router.get('/', async (ctx, next) => {
    ctx.response.body = `<h1>Index</h1>
        <form action="/login" method="post">
            <p>Name: <input name="name" value="koa"></p>
            <p>Password: <input name="password" type="password"></p>
            <p><input type="submit" value="Submit"></p>
        </form>`;
});

router.get('/goldfish',function (context,next) {
    context.response.body = '<h1>hello goldfish</h1>';
});

router.post('/login',function (context,next) {
    const username = context.request.body.name || '';
    const password = context.request.body.password || '';
    if (username === 'koa' && password === '123'){
        context.response.body = 'success!';
    } else {
        context.response.body = 'login fail';
    }
});
app.listen(8000);

上面的代码,如果响应的请求很多,通常不放在一个文件内,分多个文件写,其中请求处理部分称为controller,单独拉一个文件管理。

MVC
模板引擎部分可以使用 Nunjucks: 官方文档
在这里插入图片描述
其中 async 的响应函数就是controller,用于处理业务方面的逻辑,比如判断用户是否存在,从数据库或文件系统中读取数据等。模板就是view,用户视图展示。数据从数据库中取出来,拼接成model,再传递给view。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像识别技术在病虫害检测中的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像中提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程中,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统中,可以是移动应用、网页服务或集成到智能农业设备中。 7. **实时监测**:在实际应用中,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测中的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值