什么软件是用node.js做的(node.js能做串口通信吗)
什么软件是用node.js做的
Node 公开宣称的目标是 “旨在提供一种简单的构建可伸缩网络程序的 *** ”。当前的服务器程序有什么问题?我们来做个数学题。在 Java™ 和 PHP 这类语言中,每个连接都会生成一个新线程,每个新线程可能需要 2 MB 的配套内存。在一个拥有 8 GB RAM 的系统上,理论上更大的并发连接数量是 4,000 个用户。随着您的客户群的增长,如果希望您的 Web 应用程序支持更多用户,那么,您必须添加更多服务器。当然,这会增加服务器成本、流量成本和人工成本等成本。除这些成本上升外,还有一个潜在技术问题,即 用户可能针对每个请求使用不同的服务器,因此,任何共享资源都必须在所有服务器之间共享。鉴于上述所有原因,整个 Web 应用程序架构(包括流量、处理器速度和内存速度)中的瓶颈是:服务器能够处理的并发连接的更大数量。Node 解决这个问题的 *** 是:更改连接到服务器的方式。每个连接发射一个在 Node 引擎的进程中运行的事件,而不是为每个连接生成一个新的 OS 线程(并为其分配一些配套内存)。Node 声称它绝不会死锁,因为它根本不允许使用锁,它不会直接阻塞 I/O 调用。Node 还宣称,运行它的服务器能支持数万个并发连接。
现在您有了一个能处理数万个并发连接的程序,那么您能通过 Node 实际构建什么呢?如果您有一个 Web 应用程序需要处理这么多连接,那将是一件很 “恐怖” 的事!那是一种 “如果您有这个问题,那么它根本不是问题” 的问题。
node.js能做串口通信吗
可以的。参考:
https://github.com/voodootikigod/node-serialport
http://stackoverflow.com/questions/15028240/raspberry-pi-arduino-node-js-and-serial-port
http://www.codeproject.com/Articles/389676/Arduino-and-the-Web-using-Node *** -and-SerialPort2
search“node serialport”能找到更多资料
下面分享相关内容的知识扩展:
作为一个前端工程师,是往node方面转,还是往HTML5方面转
前景方向,nodejs与HTML5的前景都可谓一片辉煌:现在的github上js已经是最活跃的社区没有之一,而node的项目基本占了半壁江山,这是一个很活跃很年轻的领域,而且能很方便地解决很多问题
HTML5则是在各大厂的强力支持下成长的,尚在他不成熟的时候都已经有了大量的PhoneGap应用及桌面端WebView在大量使用它,应用场景相当丰富,也不会跟其它技术栈冲突
而至于说选择,我反对很多说HTML5是基础而Node是进阶的看法,因为这两个根本不是一个范畴的东西。其实在这两者之间的选择,不是纯粹的技术选择,而是关于发展方向的选择:
Node方向明显是往数据处理及其通信方向走,更偏传统程序员的进阶思路。如果你想做的是程序员,那Node就是前端更好的跳板,在这基础上再去玩其它服务甚或其它语言,都是相当不错的工具或基石;
而HTML5明显更往用户方向走,要做到的事情更多是让用户在WEB界面上能有更多样化的功能与交互体验,甚至可以在这基础上做重量级的游戏,等等。
的确,这两者是不冲突的,但从另一方面来说,两边的思维方式却又是截然不同的。作为一名前端,我更倾向于两边都有所涉猎,再根据自己的兴趣及需要进行深入研究。
怎样利用node做出可读流动模式
这次给大家带来怎样利用node做出可读流动模式,利用node做出可读流动模式的注意事项有哪些,下面就是实战案例,一起来看一下。
node的可读流基于事件
可读流之流动模式,这种流动模式会有一个"开关",每次当"开关"开启的时候,流动模式起作用,如果将这个"开关"设置成暂停的话,那么,这个可读流将不会去读取文件,直到将这个"开关"重新置为流动。
读取文件流程
读取文件内容的流程,主要为:
打开文件,打开文件成功,将触发open事件,如果打开失败,触发error事件和close事件,将文件关闭。
开始读取文件中的内容,监听data事件,数据处于流动状态,可通过修改开关的状态来暂停读取。
每次读取到的内容放入缓存中,并通过data事件将数据发布出去。
当文件中的内容读取完毕之后,将文件关闭。
这一系列动作都是基于事件来进行操作的,而node中的事件我们都知道是一种发布订阅模式来实现的。
下面我们来看一看,node是如何使用可读流来读取文件中的内容?
node 可读流参数
首先我们通过fs模块来创建一个可读流,可读流接受两个参数:
之一个参数是要读取的文件地址,在这里指明你要读取哪个文件。
第二个参数是可选项,这个参数是一个对象,用来指定可读流的一些具体的参数。
如下几个参数我们来一一说明:
highWaterMark:设置高水位线,这个参数主要用于在读取文件时,可读流会将文件中的内容读取到缓存当中,而这里我们需要创建一个buffer来缓存这些数据,所以这个参数是用来设置buffer的大小,如果不对这个参数进行设置的话,可读流默认的配置64k。
flags:这个参数主要用于设置文件的执行模式,比如说我们具体的操作适用于读取文件还是写入文件等这些操作。如果是写入文件的话那我们,使用的是w。如果是读取文件的话那这个操作符就应该是r。
下面这张表格就说明了不同的符号代表不同含义:
符号含义r读文件,文件不存在报错r+读取并写入,文件不存在报错rs同步读取文件并忽略缓存w写入文件,不存在则创建,存在则清空wx排它写入文件w+读取并写入文件,不存在则创建,存在则清空wx+和w+类似,排他方式打开a追加写入ax与a类似,排他方式写入a+读取并追加写入,不存在则创建ax+作用与a+类似,但是以排他方式打开文件autoClose:这个参数主要用于,对文件的关闭的一些控制。如果文件再打开的过程或者其他操作的过程中出现了错误的情况下,需要将文件进行关闭。那这个参数是设置文件是否自动关闭的功能。
encoding:node中用buffer来读取文件操作的东西二进制数据。这些数据展现出来的话我们是一堆乱码,所以需要,要我们对这个数据指定一个具体的编码格式。然后将会对这些数据进行编码转化,这样转化出来的数据就是我们能看懂的数据。
starts:这个参数主要用于指定从什么位置开始读取文件中的内容,默认的话是从零开始。
ends:这个参数主要用于指定定具体要读取文件多长的数据,这里需要说明一下,这个参数是包括本身的位置,也就是所谓的包前和包后。
下面我们来看看可读流具体例子:
let fs = require("fs");
let rs = fs.createReadStream("./a.js", {
highWaterMark: 3,
encoding: "utf8",
autoClose: true,
start: 0,
end: 9
});
rs.on("open", () => {console.log("open");});
rs.on("close", () => {console.log("close");});
rs.on("data", data => {
console.log(data);
rs.pause();//暂停读取 此时流动模式为暂停模式
});
setInterval(() => {
rs.resume();//重新设置为流动模式,开始读取数据
}, 1000);
rs.on("end", () => { console.log("end"); });
rs.on("error", err => { console.log(err); });手写可读流之一步
上面我们说过,node可读流是基于node的核心模块事件来完成的,所以在实现我们自己的可读流时需要继承events模块,代码如下:
let fs = require('fs');
let EventEmitter = require('events');
class ReadStream extends EventEmitter {
}继承了EventEmitter类,我们就可以使用EventEmitter类中的各个 *** ,并且同样是采用发布订阅的模式了处理事件。
第二步:处理可读流配置的参数
上面我们提到,node中创建可读流时可以对这个流配置具体的参数,比如
let rs = fs.createReadStream("./a.js", {
highWaterMark: 3,
encoding: "utf8",
autoClose: true,
start: 0,
end: 9
});那么对于这些参数,我们自己实现的可读流类也需要对这些参数进行处理,那么这些参数该如何进行处理呢?
constructor(path, options = {}) {
super();
this.path = path; //指定要读取的文件地址
this.highWaterMark = options.highWaterMark || 64 * 1024;
this.autoClose = options.autoClose || true; //是否自动关闭文件
this.start = options.start || 0; //从文件哪个位置开始读取
this.pos = this.start; // pos会随着读取的位置改变
this.end = options.end || null; // null表示没传递
this.encoding = options.encoding || null;// buffer编码
this.flags = options.flags || 'r';
this.flowing = null; // 模式开关
this.buffer = Buffer.alloc(this.highWaterMark);// 根据设置创建一个buffer存储读出来的数
this.open();
}通常配置的原则是以用户配置的参数为准,如果用户没有对这个参数进行设置的话,就采用默认的配置。
实现可读流第三步:打开文件
这里原理是使用node模块fs中的open *** 。首先我们来回顾下fs.open() *** 的使用。
fs.open(filename,flags,[mode],callback);
//实例
fs.open('./1,txt','r',function(err,fd){});这里需要说明下,回调函数callback中有2个参数:
之一个是error,node中异步回调都会返回的一个参数,用来说明具体的错误信息
第二个参数是fd,是文件描述符,用来标识文件,等价于open函数的之一个参数
好了,现在我们来看看我们自己的可读流的open *** 该如何实现吧:
open() {
fs.open(this.path, this.flags, (err, fd) => {
//fd标识的就是当前this.path这个文件,从3开始(number类型)
if (err) {
if (this.autoClose) { // 如果需要自动关闭则去关闭文件
this.destroy(); // 销毁(关闭文件,触发关闭事件)
}
this.emit('error', err); // 如果有错误触发error事件
return;
}
this.fd = fd; // 保存文件描述符
this.emit('open', this.fd); // 触发文件的打开的 ***
});
}从代码上我们可以看出:
fs.open函数是异步函数,也就是说callback是异步执行的,在成功打开文件的情况下,fd这个属性也是异步获取到的,这点需要注意。
另外重要的一点是,如果在打开文件发生错误时,则表明打开文件失败,那么此时就需要将文件关闭。
实现可读流第四步:读取文件内容
上面我们详细说过,可读流自身定义了一个"开关",当我们要读取文件中的内容的时候,我们需要将这个"开关"打开,那么node可读流本身是如何来打开这个"开关"的呢?
监听data事件
node可读流通过监听data事件来实现这个"开关"的开启:
rs.on("data", data => {
console.log(data);
});当用户监听data事件的时候,"开关"开启,不停的从文件中读取内容。那么node是怎么监听data事件的呢?
答案就是 事件模块的newListener
这是因为node可读流是基于事件的,而事件中,服务器就可以通过newListener事件监听到从用户这边过来的所有事件,每个事件都有对应的类型,当用户监听的是data事件的时候,我们就可以获取到,然后就可以去读取文件中的内容了,那我们自己的可读流该如何实现呢?
// 监听newListener事件,看是否监听了data事件,如果监听了data事件的话,就开始启动流动模式,读取文件中的内容
this.on("newListener", type => {
if (type === "data") {
// 开启流动模式,开始读取文件中的内容
this.flowing = true;
this.read();
}
});好了,知道了这个"开关"是如何打开的,那么这个时候就到了真正读取文件中内容的关键时候了,先上代码先:
read() {
// 之一次读取文件的话,有可能文件是还没有打开的,此时this.fd可能还没有值
if (typeof this.fd !== "number") {
// 如果此时文件还是没有打开的话,就触发一次open事件,这样文件就真的打开了,然后再读取
return this.once("open", () => this.read());
}
// 具体每次读取多少个字符,需要进行计算,因为最后一次读取倒的可能比highWaterMark小
let howMuchRead = this.end ? Math.min(this.end - this.pos + 1, this.highWaterMark) : this.highWaterMark;
fs.read(this.fd, this.buffer, 0, howMuchRead, this.pos, (err, byteRead) => {
// this.pos 是每次读取文件读取的位置,是一个偏移量,每次读取会发生变化
this.pos += byteRead;
// 将读取到的内容转换成字符串串,然后通过data事件,将内容发布出去
let srr = this.encoding ? this.buffer.slice(0, byteRead).toString(this.encoding) : this.buffer.slice(0, byteRead);
// 将内容通过data事件发布出去
this.emit("data", srr);
// 当读取到到内容长度和设置的highWaterMark一致的话,并且还是流动模式的话,就继续读取
if ((byteRead === this.highWaterMark) && this.flowing) {
return this.read();
}
// 没有更多的内容了,此时表示文件中的内容已经读取完毕
if (byteRead < this.highWaterMark) {
// 读取完成,发布end *** ,并关闭文件
this.emit("end");
this.destory();
}
});
}这里我们特别要注意的是:
文件是否已经打开,是否获取到fd,如果没有打开的话,则再次触发open ***
分批次读取文件内容,每次读取的内容是变化的,所以位置和偏移量是要动态计算的
控制读取停止的条件。
实现可读流第五步:关闭文件
好了,到现在,基础的读取工作已经完成,那么就需要将文件关闭了,上面的open和read *** 里面都调用了一个 *** :destory,没错,这个就是关闭文件的 *** ,好了,那么我们来看看这个 *** 该如何实现吧
destory() {
if (typeof this.fd !== "number") {
// 发布close事件
return this.emit("close");
}
// 将文件关闭,发布close事件
fs.close(this.fd, () => {
this.emit("close");
});
}当然这块的原理就是调用fs模块的close *** 啦。
实现可读流第六步:暂停和恢复
既然都说了,node可读流有一个神奇的"开关",就像大坝的阀门一样,可以控制水的流动,同样也可以控制水的暂停啦。当然在node可读流中的暂停是停止对文件的读取,恢复就是将开关打开,继续读取文件内容,那么这两个分别对应的 *** 就是pause()和resume() *** 。
那么我们自己的可读流类里面该如何实现这两个 *** 的功能呢?非常简单:
我们在定义类的私有属性的时候,定义了这样一个属性flowing,当它的值为true时表示开关打开,反之关闭。
pause() {
this.flowing = false;// 将流动模式设置成暂停模式,不会读取文件
}
resume() {
this.flowing = true;//将模式设置成流动模式,可以读取文件
this.read();// 重新开始读取文件
}相信看了本文案例你已经掌握了 *** ,更多精彩请关注Gxl网其它相关文章!
推荐阅读:
怎样利用 *** 做出引用传递与值传递
使用 *** 实做出加密解密操作
如何用 node *** 做后端开发?
Node.js 是一种基于 Chrome V8 引擎的 JavaScript 运行时,它可以用于开发后端应用程序。以下是一些步骤,可以帮助您开始使用 Node.js 进行后端开发:1. 安装 Node.js:请访问 Node.js 官网(https://nodejs.org/)下载并安装适合您操作系统的版本。
2. 学习 JavaScript:Node.js 是 JavaScript 的运行时,因此您需要熟悉 JavaScript 语言才能更好地使用它。
3. 学习 Express:Express 是一个基于 Node.js 的 Web 应用程序框架,可以帮助您快速构建 Web 应用程序。请访问 Express 官网(https://expressjs.com/)下载并安装适合您项目的版本。
4. 学习 MongoDB:MongoDB 是一个 NoSQL 数据库,可以帮助您存储和管理数据。请访问 MongoDB 官网(https://www.mongodb.com/)下载并安装适合您项目的版本。
5. 学习其他技术:除了上述技术之外,还有许多其他技术可以帮助您更好地使用 Node.js 进行后端开发,例如 Koa、Socket.IO、Nest *** 等等。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。