通过异步迭代简化Node.js流程

来源:岁月联盟 编辑:猪蛋儿 时间:2020-01-29

如果我们使用异步迭代,那么使用Node.js流程将更加高效。
异步迭代和异步生成器
异步迭代是用于异步检索数据容器内容的协议,这也意味着当前“任务”可以在检索项目之前被暂停。
异步生成器有助于异步迭代,如下所示,就是一个异步生成器函数:
/**
 * @returns an asynchronous iterable
 */
async function* asyncGenerator(asyncIterable) {
  for await (const item of asyncIterable) { // input
    if (···) {
      yield '> ' + item; // output
    }
  }
}
for-await-of循环遍历输入asyncIterable,这个循环在普通的异步函数中也可用。另外,yield将值输入到此生成器返回的异步迭代中。
接下里,请密切关注以下函数是异步函数还是异步生成器函数:
/** @returns a Promise */
async function asyncFunction() { /*···*/ }
/** @returns an async iterable */
async function* asyncGeneratorFunction() { /*···*/ }
Node.js支持多种流程,例如:
1.可读流程(Readable stream)是我们可以从中读取数据的流程,换句话说,它们是数据的源头。比如可读的文件流程,它允许我们读取文件的内容。
2.可写流程(Writable stream)是我们可以写入数据的流程,换句话说,它们是数据的接收器。比如可写的文件流程,它允许我们将数据写入文件。
3.转换流程(transform stream)既可读又可写,作为可写流程时,它接收数据片段,对其进行转换,更改或删除它们,然后将它们作为可读流程输出。
流水线技术(Pipelining)
计算机中的流水线是把一个重复的过程分解为若干个子过程,每个子过程与其他子过程并行进行。由于这种工作方式与工厂中的生产流水线十分相似, 因此称为流水线技术。从本质上讲,流水线技术是一种时间并行技术。
要在多个步骤中处理流程数据,即可使用流水线技术:
1.通过可读的流程接收输入;
2.每个处理步骤都是通过转换流程执行的;
3.对于最后一个处理步骤,我们有两个选项:
3.1我们可以将最近的可读流程中的数据写入可写流程,也就是说,可写流程是流水线上的最后一个进程。
3.2我们可以以其他方式处理最近的可读流程中的数据;
其中,第2个选项是可选的。
文本编码
当创建文本流程时,最好一直指定一个编码:
Node.js文档有一个支持编码和默认拼写的列表,如下所示:
'utf8'
'utf16le'
'base64'
也可以使用一些不同的拼写,你可以使用Buffer.isEncoding()来检查哪些是:
> buffer.Buffer.isEncoding('utf8')
true
> buffer.Buffer.isEncoding('utf-8')
true
> buffer.Buffer.isEncoding('UTF-8')
true
> buffer.Buffer.isEncoding('UTF:8')
false
编码的默认值是null,它相当于'utf8'。
辅助函数:readableToString() 
有时候,我们会使用以下辅助函数。不过在本文中,你不需要具体了解它是如何工作的,大致了解既可。
import * as stream from 'stream';
/**
 * Reads all the text in a readable stream and returns it as a string,
 * via a Promise.
 * @param {stream.Readable} readable
 */
function readableToString(readable) {
  return new Promise((resolve, reject) => {
    let data = '';
    readable.on('data', function (chunk) {
      data += chunk;
    });
    readable.on('end', function () {
      resolve(data);
    });
    readable.on('error', function (err) {
      reject(err);
    });
  });
}
这个函数是通过基于事件的API实现的,稍后我们将看到一种更简单的方法,即通过异步迭代方法。
在这篇文章中,我们将只使用文本流程。
在这些示例中,我们偶尔会遇到在顶层使用await的情况。在本文的示例中,我们假设我们在模块内部或异步函数的主体内部。
每当有换行符时,我们都会使用以下函数:
Unix: '/n' (LF)
Windows: '/r/n' (CR LF)
可以通过模块os中的常量EOL访问当前平台的换行符
可读的流程
创建可读的流程
可以从文件中创建可读的流程,具体来说,我们可以使用fs.createReadStream()来创建可读的流程:
import * as fs from 'fs';
const readableStream = fs.createReadStream(
  'tmp/test.txt', {encoding: 'utf8'});
assert.equal(
  await readableToString(readableStream),
  'This is a test!/n');
Readable.from():通过可迭代器创建可读流程
静态方法readable .from(iterable, options?)可以创建一个可读的流程,该流程包含可迭代器中包含的数据。可迭代可以是同步迭代的,也可以是异步迭代的。参数选项是可选的,还可以用于指定文本编码。
import * as stream from 'stream';
function* gen() {
  yield 'One line/n';
  yield 'Another line/n';
}
const readableStream = stream.Readable.from(gen(), {encoding: 'utf8'});
assert.equal(
  await readableToString(readableStream),
  'One line/nAnother line/n');
通过字符串创建可读的流程
Readable.from() 接受任何可迭代的对象,同时也可以用来将字符串转换成流程:
import {Readable} from 'stream';
const str = 'Some text!';
const readable = Readable.from(str, {encoding: 'utf8'});
assert.equal(
  await readableToString(readable),

[1] [2] [3]  下一页