2019.01.30
5225
最近读《重学前端》,开篇就是让你拥有自己的知识体系图谱,后续学的东西补充到相应的模块,既可以加深对原有知识的理解,又可以强化记忆,很不错的学习方案。
理解流的最好方式就是想象一下没有流的时候怎么处理数据:
想要通过网络高效且支持大文件的发送一个文件到一个客户端。
const http = require('http'); const fs = require('fs');
http.createServer((req, res) => {
fs.readFile(`${__dirname}/index.html`, (err, data) => { if (err) {
res.statusCode = 500;
res.end(String(err)); return;
}
res.end(data);
});
}).listen(8000); 复制代码
const http = require('http'); const fs = require('fs');
http.createServer((req, res) => {
fs.createReadStream(`${__dirname}/index.html`).pipe(res);
}).listen(8000); 复制代码
const http = require('http'); const fs = require('fs'); const zlib = require('zlib');
http.createServer((req, res) => {
res.writeHead(200, { 'content-encoding': 'gzip',
});
fs.createReadStream(`${__dirname}/index.html`)
.pipe(zlib.createGzip())
.pipe(res);
}).listen(8000); 复制代码
const fs = require('fs'); const stream = fs.createReadStream('not-found');
stream.on('error', (err) => { console.trace(); console.error('Stack:', err.stack); console.error('The error raised was:', err);
}); 复制代码
可读流被用来为 I/O 源提供灵活的 API,也可以被用作解析器:
json-lines.txt
{ "position": 0, "letter": "a" }
{ "position": 1, "letter": "b" }
{ "position": 2, "letter": "c" }
{ "position": 3, "letter": "d" }
{ "position": 4, "letter": "e" }
{ "position": 5, "letter": "f" }
{ "position": 6, "letter": "g" }
{ "position": 7, "letter": "h" }
{ "position": 8, "letter": "i" }
{ "position": 9, "letter": "j" } 复制代码
JSONLineReader.js
const stream = require('stream'); const fs = require('fs'); const util = require('util'); class JSONLineReader extends stream.Readable { constructor(source) { super(); this._source = source; this._foundLineEnd = false; this._buffer = '';
source.on('readable', () => { this.read();
});
} // 所有定制 stream.Readable 类都需要实现 _read 方法 _read(size) { let chunk; let line; let result; if (this._buffer.length === 0) {
chunk = this._source.read(); this._buffer += chunk;
} const lineIndex = this._buffer.indexOf('\n'); if (lineIndex !== -1) {
line = this._buffer.slice(0, lineIndex); // 从 buffer 的开始截取第一行来获取一些文本进行解析 if (line) {
result = JSON.parse(line); this._buffer = this._buffer.slice(lineIndex + 1); this.emit('object', result); // 当一个 JSON 记录解析出来的时候,触发一个 object 事件 this.push(util.inspect(result)); // 将解析好的 SJON 发回内部队列 } else { this._buffer = this._buffer.slice(1);
}
}
}
} const input = fs.createReadStream(`${__dirname}/json-lines.txt`, { encoding: 'utf8',
}); const jsonLineReader = new JSONLineReader(input); // 创建一个 JSONLineReader 实例,传递一个文件流给它处理 jsonLineReader.on('object', (obj) => { console.log('pos:', obj.position, '- letter:', obj.letter);
}); 复制代码
可写的流可用于输出数据到底层 I/O:
cat json-lines.txt | node stram_writable.js 复制代码
stram_writable.js
const stream = require('stream'); class GreenStream extends stream.Writable { constructor(options) { super(options);
}
_write(chunk, encoding, cb) {
process.stdout.write(`\u001b[32m${chunk}\u001b[39m`);
cb();
}
}
process.stdin.pipe(new GreenStream()); 复制代码
双工流允许发送和接受数据:
使用流改变数据为另一种格式,并且高效地管理内存:
使用 Node 内置的断言模块测试
const assert = require('assert'); const fs = require('fs'); const CSVParser = require('./csvparser'); const parser = new CSVParser(); const actual = [];
fs.createReadStream(`${__dirname}/sample.csv`)
.pipe(parser);
process.on('exit', function () {
actual.push(parser.read());
actual.push(parser.read());
actual.push(parser.read()); const expected = [
{ name: 'Alex', location: 'UK', role: 'admin' },
{ name: 'Sam', location: 'France', role: 'user' },
{ name: 'John', location: 'Canada', role: 'user' },
];
assert.deepEqual(expected, actual);
});
2023.03.08
407
编者按:为什么所有的好莱坞科幻电影当中,用户界面看起来都是一样透明、蓝色 UI 乃至于全息投影?这种风尚是如何流行开的?它们对于未来的 UI 设计有影响么?目前全息影像发展到什么程度了?