node.js流媒体
Streams are one of the fundamental concepts that power Node.js applications.
流是为Node.js应用程序提供动力的基本概念之一。
They are a way to handle reading/writing files, network communications, or any kind of end-to-end information exchange in an efficient way.
它们是一种以有效方式处理读/写文件,网络通信或任何类型的端到端信息交换的方式。
Streams are not a concept unique to Node.js. They were introduced in the Unix operating system decades ago, and programs can interact with each other passing streams through the pipe operator (|
).
流不是Node.js特有的概念。 它们是几十年前在Unix操作系统中引入的,程序可以通过管道运算符( |
)使流相互交互。
For example, in the traditional way, when you tell the program to read a file, the file is read into memory, from start to finish, and then you process it.
例如,以传统方式,当您告诉程序读取文件时,会将文件从头到尾读入内存,然后进行处理。
Using streams you read it piece by piece, processing its content without keeping it all in memory.
使用流,您可以逐段读取它,处理其内容而不将其全部保存在内存中。
The Node.js stream
module provides the foundation upon which all streaming APIs are build.
Node.js stream
模块提供了构建所有流API的基础。
Streams basically provide two major advantages using other data handling methods:
使用其他数据处理方法,流基本上提供了两个主要优点:
Memory efficiency: you don’t need to load large amounts of data in memory before you are able to process it
内存效率 :您无需先在内存中加载大量数据,然后再进行处理
Time efficiency: it takes way less time to start processing data as soon as you have it, rather than waiting till the whole data payload is available to start
时间效率 :拥有数据后立即开始处理数据所需的时间更少,而不必等到整个数据有效负载都可开始使用
A typical example is the one of reading files from a disk.
一个典型的例子是从磁盘读取文件的例子。
Using the Node fs
module you can read a file, and serve it over HTTP when a new connection is established to your http server:
使用Node fs
模块,您可以读取文件,并在与http服务器建立新连接时通过HTTP提供文件:
const http = require('http')
const fs = require('fs')
const server = http.createServer(function (req, res) {
fs.readFile(__dirname + '/data.txt', (err, data) => {
res.end(data)
})
})
server.listen(3000)
readFile()
reads the full contents of the file, and invokes the callback function when it’s done.
readFile()
读取文件的全部内容,并在完成后调用回调函数。
res.end(data)
in the callback will return the file contents to the HTTP client.
回调中的res.end(data)
会将文件内容返回给HTTP客户端。
If the file is big, the operation will take quite a bit of time. Here is the same thing written using streams:
如果文件很大,则该操作将花费大量时间。 这是使用流编写的相同内容:
const http = require('http')
const fs = require('fs')
const server = http.createServer((req, res) => {
const stream = fs.createReadStream(__dirname + '/data.txt')
stream.pipe(res)
})
server.listen(3000)
Instead of waiting until the file is fully read, we start streaming it to the HTTP client as soon as we have a chunk of data ready to be sent.
我们没有等待直到文件被完全读取,而是在准备好要发送的大量数据后立即开始将其流式传输到HTTP客户端。
The above example uses the line stream.pipe(res)
: the pipe()
method is called on the file stream.
上面的示例使用stream.pipe(res)
:在文件流上调用pipe()
方法。
What does this code do? It takes the source, and pipes it into a destination.
该代码的作用是什么? 它获取源,并将其通过管道传输到目标。
You call it on the source stream, so in this case, the file stream is piped to the HTTP response.
您在源流上调用它,因此在这种情况下,文件流通过管道传递到HTTP响应。
The return value of the pipe()
method is the destination stream, which is a very convenient thing that lets us chain multiple pipe()
calls, like this:
pipe()
方法的返回值是目标流,这是非常方便的事情,它使我们可以链接多个pipe()
调用,如下所示:
src.pipe(dest1).pipe(dest2)
This construct is the same as doing
此构造与执行相同
src.pipe(dest1)
dest1.pipe(dest2)
Due to their advantages, many Node.js core modules provide native stream handling capabilities, most notably:
由于它们的优点,许多Node.js核心模块提供了本机流处理功能,最值得注意的是:
process.stdin
returns a stream connected to stdin
process.stdin
返回连接到stdin的流
process.stdout
returns a stream connected to stdout
process.stdout
返回连接到stdout的流
process.stderr
returns a stream connected to stderr
process.stderr
返回连接到stderr的流
fs.createReadStream()
creates a readable stream to a file
fs.createReadStream()
创建文件的可读流
fs.createWriteStream()
creates a writable stream to a file
fs.createWriteStream()
创建到文件的可写流
net.connect()
initiates a stream-based connection
net.connect()
启动基于流的连接
http.request()
returns an instance of the http.ClientRequest class, which is a writable stream
http.request()
返回http.ClientRequest类的实例,该实例是可写的流
zlib.createGzip()
compress data using gzip (a compression algorithm) into a stream
zlib.createGzip()
使用gzip(一种压缩算法)将数据压缩到流中
zlib.createGunzip()
decompress a gzip stream.
zlib.createGunzip()
解压缩gzip流。
zlib.createDeflate()
compress data using deflate (a compression algorithm) into a stream
zlib.createDeflate()
使用deflate(压缩算法)将数据压缩到流中
zlib.createInflate()
decompress a deflate stream
zlib.createInflate()
解压缩deflate流
There are four classes of streams:
流分为四类:
Readable
: a stream you can pipe from, but not pipe into (you can receive data, but not send data to it). When you push data into a readable stream, it is buffered, until a consumer starts to read the data.
Readable
:可以通过管道传输但不能通过管道传输的流(您可以接收数据,但不能向其发送数据)。 当您将数据推送到可读流中时,将对其进行缓冲,直到使用者开始读取数据为止。
Writable
: a stream you can pipe into, but not pipe from (you can send data, but not receive from it)
Writable
:您可以通过管道传输而不是从管道传输的流(您可以发送数据,但不能接收数据)
Duplex
: a stream you can both pipe into and pipe from, basically a combination of a Readable and Writable stream
Duplex
:您可以同时通过管道传输和传输的流,基本上是可读流和可写流的组合
Transform
: a Transform stream is similar to a Duplex, but the output is a transform of its input
Transform
:转换流类似于双工,但输出是其输入的转换
We get the Readable stream from the stream
module, and we initialize it
我们从stream
模块获取Readable流,并对其进行初始化。
const Stream = require('stream')
const readableStream = new Stream.Readable()
Now that the stream is initialized, we can send data to it:
现在,流已初始化,我们可以向其发送数据了:
readableStream.push('hi!')
readableStream.push('ho!')
To create a writable stream we extend the base Writable
object, and we implement its _write() method.
要创建可写流,我们扩展基本Writable
对象,并实现其_write()方法。
First create a stream object:
首先创建一个流对象:
const Stream = require('stream')
const writableStream = new Stream.Writable()
then implement _write
:
然后实现_write
:
writableStream._write = (chunk, encoding, next) => {
console.log(chunk.toString())
next()
}
You can now pipe a readable stream in:
现在,您可以通过以下方式传递可读流:
process.stdin.pipe(writableStream)
How do we read data from a readable stream? Using a writable stream:
我们如何从可读流中读取数据? 使用可写流:
const Stream = require('stream')
const readableStream = new Stream.Readable()
const writableStream = new Stream.Writable()
writableStream._write = (chunk, encoding, next) => {
console.log(chunk.toString())
next()
}
readableStream.pipe(writableStream)
readableStream.push('hi!')
readableStream.push('ho!')
You can also consume a readable stream directly, using the readable
event:
您还可以使用readable
事件直接使用可读流:
readableStream.on('readable', () => {
console.log(readableStream.read())
})
Using the stream write()
method:
使用流write()
方法:
writableStream.write('hey!\n')
Use the end()
method:
使用end()
方法:
const Stream = require('stream')
const readableStream = new Stream.Readable()
const writableStream = new Stream.Writable()
writableStream._write = (chunk, encoding, next) => {
console.log(chunk.toString())
next()
}
readableStream.pipe(writableStream)
readableStream.push('hi!')
readableStream.push('ho!')
writableStream.end()
node.js流媒体