Nó hoạt động tốt
global.foo = function foo [] {
console.log["foo was called"];
}
process.stdin.on["data", function[input] {
// don't forget to call .trim[] to remove the \n
var fn = input.toString[].trim[];
// function exists
if [fn in global && typeof global[fn] === "function"] {
global[fn][];
}
// function does not exist
else {
console.log["could not find " + fn + " function"];
}
}];
process.stdin.resume[];
Đầu ra
foo
foo was called
bar
could not find bar function
Cho dù đây có phải là một ý kiến hay không ... tốt, đó là một cuộc thảo luận hoàn toàn khác. well, that's an entirely different discussion.
Chỉnh sửa - ≈18 tháng sau ... Vâng, đó là một ý tưởng khủng khiếp khi gọi một chức năng toàn cầu như thế. — ≈18 months later... Yeah, it's a horrible idea to call a global function like that.
Nói rằng, đây là một cách bạn có thể tiếp cận vấn đề theo một cách tốt hơn nhiều. Dưới đây chúng tôi sẽ xây dựng một ít thay đổi [vòng lặp in-eval in]. Để hiểu rõ hơn, tôi sẽ chia nó thành một vài phần.
Đầu tiên, chúng tôi muốn đảm bảo rằng người dùng thay thế của chúng tôi sẽ nhấn ENTER trước khi chúng tôi thử chạy lệnh của họ. Để làm điều đó, chúng tôi sẽ tạo một luồng biến đổi chờ một ký tự
foo
foo was called
bar
could not find bar function
1 trước khi gửi foo
foo was called
bar
could not find bar function
2 xuống đường ốngMã dưới đây được viết bằng ES6. Nếu bạn gặp khó khăn trong việc tìm kiếm một môi trường tương thích để chạy mã, tôi khuyên bạn nên kiểm tra Babel.
// line-unitizer.js
import {Transform} from 'stream';
class LineUnitizer extends Transform {
constructor[delimiter="\n"] {
super[];
this.buffer = "";
this.delimiter = delimiter;
}
_transform[chunk, enc, done] {
this.buffer += chunk.toString[];
var lines = this.buffer.split[this.delimiter];
this.buffer = lines.pop[];
lines.forEach[line => this.push[line]];
done[];
}
}
export default LineUnitizer;
Đừng quá treo trên
foo
foo was called
bar
could not find bar function
3 nếu bạn mới xử lý luồng và nó không hoàn toàn có ý nghĩa. Loại biến đổi luồng này là vô cùng phổ biến. Ý tưởng chung là thế này: Một khi chúng ta đưa foo
foo was called
bar
could not find bar function
4 vào luồng nhận, foo
foo was called
bar
could not find bar function
4 sẽ phát ra dữ liệu mỗi khi người dùng nhấn phím. Tuy nhiên, foo
foo was called
bar
could not find bar function
6 của chúng tôi [được triển khai bên dưới] không thể hành động trên lệnh cho đến khi người dùng gõ xong lệnh. foo
foo was called
bar
could not find bar function
3 là phần chờ người dùng nhấn Enter [chèn foo
foo was called
bar
could not find bar function
1 vào luồng] và sau đó báo hiệu cho foo
foo was called
bar
could not find bar function
9 rằng lệnh đã sẵn sàng để được gửi đến // line-unitizer.js
import {Transform} from 'stream';
class LineUnitizer extends Transform {
constructor[delimiter="\n"] {
super[];
this.buffer = "";
this.delimiter = delimiter;
}
_transform[chunk, enc, done] {
this.buffer += chunk.toString[];
var lines = this.buffer.split[this.delimiter];
this.buffer = lines.pop[];
lines.forEach[line => this.push[line]];
done[];
}
}
export default LineUnitizer;
0 để xử lý!Hãy nhìn vào
foo
foo was called
bar
could not find bar function
6 bây giờ// repl.js
import {Writable} from 'stream';
class Repl extends Writable {
_parse[line] {
var [cmd, ...args] = line.split[/\s+/];
return {cmd, args};
}
_write[line, enc, done] {
var {cmd, args} = this._parse[line.toString[]];
this.emit[cmd, args];
done[];
}
}
export default Repl;
Vâng, điều đó thật dễ dàng! Nó làm gì tho? Mỗi lần
// line-unitizer.js
import {Transform} from 'stream';
class LineUnitizer extends Transform {
constructor[delimiter="\n"] {
super[];
this.buffer = "";
this.delimiter = delimiter;
}
_transform[chunk, enc, done] {
this.buffer += chunk.toString[];
var lines = this.buffer.split[this.delimiter];
this.buffer = lines.pop[];
lines.forEach[line => this.push[line]];
done[];
}
}
export default LineUnitizer;
0 nhận được một dòng, nó phát ra một sự kiện với một số cuộc tranh luận. Đây là một cách trực quan để xem cách một lệnh được phân tích cú phápThe user enters emit event args
-------------------------------------------------------------
add 1 2 3 "add" ["1", "2", "3"]
hens chocobo cucco "hens" ["chocobo", "cucco"]
yay "yay" []
Được rồi, bây giờ chúng ta hãy kết nối mọi thứ cùng nhau để thấy nó hoạt động
// start.js
import LineUnitizer from './line-unitizer';
import Repl from './repl';
process.stdin
.pipe[new LineUnitizer[]]
.pipe[
[new Repl[]]
.on["add", function[args] {
var sum = args.map[Number].reduce[[a,b] => a+b, 0];
console.log["add result: %d", sum];
}]
.on["shout", function[args] {
var allcaps = args.map[s => s.toUpperCase[]].join[" "];
console.log[allcaps];
}]
.on["exit", function[args] {
console.log["kthxbai!"];
process.exit[];
}]];
Chạy nó
$ node start.js
Đầu ra
Các dòng có tiền tố với
3 là đầu vào của người dùng.// line-unitizer.js import {Transform} from 'stream'; class LineUnitizer extends Transform { constructor[delimiter="\n"] { super[]; this.buffer = ""; this.delimiter = delimiter; } _transform[chunk, enc, done] { this.buffer += chunk.toString[]; var lines = this.buffer.split[this.delimiter]; this.buffer = lines.pop[]; lines.forEach[line => this.push[line]]; done[]; } } export default LineUnitizer;
3 sẽ không thực sự nhìn thấy trong thiết bị đầu cuối của bạn.// line-unitizer.js import {Transform} from 'stream'; class LineUnitizer extends Transform { constructor[delimiter="\n"] { super[]; this.buffer = ""; this.delimiter = delimiter; } _transform[chunk, enc, done] { this.buffer += chunk.toString[]; var lines = this.buffer.split[this.delimiter]; this.buffer = lines.pop[]; lines.forEach[line => this.push[line]]; done[]; } } export default LineUnitizer;
> add 1 2 3
add result: 6
> shout I can see it in your face!
I CAN SEE IT IN YOUR FACE!
> exit
kthxbai!
Nếu bạn nghĩ điều đó thật tuyệt vời, chúng tôi thậm chí còn chưa hoàn thành. Lợi ích của việc viết chương trình của chúng tôi theo cách này là chúng tôi có thể hành động trên các lệnh bất kể họ đến chương trình của chúng tôi như thế nào.
Xem xét tệp
// line-unitizer.js
import {Transform} from 'stream';
class LineUnitizer extends Transform {
constructor[delimiter="\n"] {
super[];
this.buffer = "";
this.delimiter = delimiter;
}
_transform[chunk, enc, done] {
this.buffer += chunk.toString[];
var lines = this.buffer.split[this.delimiter];
this.buffer = lines.pop[];
lines.forEach[line => this.push[line]];
done[];
}
}
export default LineUnitizer;
5 nàyadd 100 200
shout streams are the bee's knees
exit
Bây giờ chạy nó như thế này
$ cat commands.txt | node start.js
Đầu ra
foo
foo was called
bar
could not find bar function
0Ok, đó là điều khá tuyệt vời. Bây giờ hãy xem xét rằng các lệnh có thể đến từ bất cứ đâu. Có thể là một sự kiện cơ sở dữ liệu, một cái gì đó trên mạng, một công việc cron, v.v. bởi vì mọi thứ được phân tách độc đáo, chúng tôi có thể dễ dàng điều chỉnh chương trình này để chấp nhận nhiều đầu vào một cách dễ dàng.