javascript - 直接传递 process.stdout.write 与通过回调传递不同的输出?
问题描述
我不太确定为什么会这样,但是我写了以下内容:
const runScript = (cmd, args) => {
return new Promise((res, rej) => {
// spawn a new process
const ls = spawn(cmd, args);
ls.stdout.on("data", (data) => {process.stdout.write(data)});
ls.stderr.on("data", (data) => {process.stderr.write(data)});
ls.on("close", code => {
console.log(`Command ${cmd} ${args} exited with code ${code}`);
code === 0 ? res(code) : rej(code);
});
ls.on("error", code => {
rej(code);
});
});
};
这工作正常。但我想我可以将.on("data")
事件处理程序更改为直接传入 write 函数。所以我从
ls.stdout.on("data", (data) => {process.stdout.write(data)});
至
ls.stdout.on("data", process.stdout.write);
根据命令,重构版本(.write
直接传递)或 EPIPE 都没有输出。我以为他们完全一样。这里到底发生了什么?我怀疑它与缓冲或process
所指的内容有关。
解决方案
当您process.stdout.write
作为参数传递时,它会读取 的值process.stdout.write
并将函数指针传递给该write
方法。然后,当ls.staout.on()
稍后调用该方法时,它不受约束process.stdout
并且无法正常工作。
相反,改为:
ls.stdout.on("data", process.stdout.write.bind(process.stdout));
并且,当它被调用时,它将正确地绑定到所需的对象。
有关如何在函数内部进行控制的摘要,请参阅如何在函数调用中设置 thisthis
。
作为一个更简单的示例,请参见:
class X {
constructor(val) {
this.val = val;
}
add(otherVal) {
return this.val + otherVal;
}
}
let x = new X(3);
let fn = x.add;
fn(5); // doesn't work properly
可以正常工作的示例:
let x = new X(3);
x.add(5); // obj.method() sets proper value of this to obj in the method
或者,如果您想传递该方法:
let x = new X(3);
let fn = x.add;
fn.call(x, 5); // fn.call(x) artificially sets this to x inside the method
或这个:
let x = new X(3);
let fn = x.add.bind(x); // creates stub function that calls method properly
fn(5);
这也不起作用,因为当fn(5)
被调用时,没有绑定到x
对象,所以当函数运行时,对方法this
内部的引用add()
将没有正确的值this
并且它不会正常工作。
当此代码执行let fn = x.add
时,它会获得一个指向该add
方法的指针,但没有绑定到该x
对象。那会丢失。然后,当你调用时fn(5)
,由于this
Javascript 中的值是根据函数的调用方式设置的,所以这只是一个普通的函数调用,所以this
值设置为undefined
(在严格模式下)或全局对象(在非严格模式下) . 在任何一种情况下,它都不是所需的x
对象。为了使它成为x
对象,它必须被调用,因为x.fn()
值必须人为地设置一些其他方法,this
例如 with或。 .apply()
.call()
.bind()
在上述情况下,由于您不控制函数的调用者(它被您无法控制的其他代码调用),因此.bind()
是一个合适的解决方案。
推荐阅读
- c# - 如何确保在 C# 中没有按下按钮?
- python - 类方法可以调用python中的实例方法吗?
- api - 是否可以通过 REST api 将新的 TFS 用户故事添加到 backlog 的顶部?
- forms - 访问:打开新表单时打开当前记录
- python - 如果 Box 中不存在,则使用 Python 动态创建多个文件夹
- jbpm - 从 jBPM 导出流程
- html - 如何使介绍动画在最后消失或使用 CSS 引导到主页?
- flutter - 如何访问和更改在 FLUTTER/DART 的另一个类中声明的字符串变量的值
- python - 寻找最大的二元差距
- laravel - Laravel after_or_equal 验证返回今天之前日期的错误状态码