stderr.on('data') 无法调用 ES6 class 返回此方法的方法
ES6 class method returning this can't be called by stderr.on('data')
学习 ES6 / NodeJS / JavaScript classes 的细节。我创建了一个日志脚本,并将其传递给 child_process。首先,这里是日志 class ./bin/log
:
'use strict';
const fs = require('fs')
const mkdirp = require('mkdirp')
module.exports = class Log {
constructor(logDir='./', name='log.log.txt', callback = ()=>{}) {
let dt = new Date()
this.dir = dt.getFullYear() + '-' + ('0' + (Number(dt.getMonth()) + 1).toString()).slice(-2) + '-' + ('0' + dt.getDate()).slice(-2)
this.filename = `${logDir}${this.dir}/${name}.${Math.round(Date.now())}.log.txt`
mkdirp(logDir + this.dir + '/', (err) => {
if (err) return callback(err);
fs.appendFile(this.filename, `${process.argv.join(' ')}\n${dt.toString()}\n`, (e) => {
if (e) return callback(e);
callback(null);
})
})
}
log(msg='') {
fs.appendFileSync(this.filename, msg.toString() + '\n');
return this;
}
err(e='') {
fs.appendFileSync(this.filename, `Error!: ${e.toString()}\n`);
return this;
}
}
所以这在我的主文件中有效:
const child_process = require('child_process')
const Log = require('./bin/log')
let log = new Log('./logs/', 'KPI-Update', function(e) {
if (e) return console.error(e);
let child = child_process.spawn("Rscript", ["./bin/main.R"])
child.stderr.on("data",(d)=>{log.err(d)})
child.stdout.on("data",(d)=>{log.log(d)})
child.stdout.on("close",(d)=>{log.log(d)})
})
但这只适用于第一次调用(在第二次调用时,this
的上下文已更改为 child_process 套接字。我在这里不明白什么?
child.stderr.on("data",log.err)
child.stdout.on("data",log.log)
child.stdout.on("close",log.log)
child.stderr.on("data",log.err)
就像
let err = log.err;
child.stderr.on("data", err)
意味着你正在从 class 中提取一个函数并将其作为回调传递,但是当你像那样提取一个函数时,它将不再将正确的 this
值传递给err
函数调用时。当你这样做时
(d) => log.err(d)
您正在创建一个将正确调用 log.err
的新函数。
另一种方法是您可以这样做
child.stderr.on("data", log.err.bind(this))
或者在你的 class 构造函数中你可以做
this.log = this.log.bind(this);
this.err = this.err.bind(this);
用具有正确this
强制集的实例变量覆盖class原型中的函数,然后
child.stderr.on("data", log.err)
可以正常工作。
我建议您阅读 this
的工作原理,因为这似乎是这个问题的主要触发点。
学习 ES6 / NodeJS / JavaScript classes 的细节。我创建了一个日志脚本,并将其传递给 child_process。首先,这里是日志 class ./bin/log
:
'use strict';
const fs = require('fs')
const mkdirp = require('mkdirp')
module.exports = class Log {
constructor(logDir='./', name='log.log.txt', callback = ()=>{}) {
let dt = new Date()
this.dir = dt.getFullYear() + '-' + ('0' + (Number(dt.getMonth()) + 1).toString()).slice(-2) + '-' + ('0' + dt.getDate()).slice(-2)
this.filename = `${logDir}${this.dir}/${name}.${Math.round(Date.now())}.log.txt`
mkdirp(logDir + this.dir + '/', (err) => {
if (err) return callback(err);
fs.appendFile(this.filename, `${process.argv.join(' ')}\n${dt.toString()}\n`, (e) => {
if (e) return callback(e);
callback(null);
})
})
}
log(msg='') {
fs.appendFileSync(this.filename, msg.toString() + '\n');
return this;
}
err(e='') {
fs.appendFileSync(this.filename, `Error!: ${e.toString()}\n`);
return this;
}
}
所以这在我的主文件中有效:
const child_process = require('child_process')
const Log = require('./bin/log')
let log = new Log('./logs/', 'KPI-Update', function(e) {
if (e) return console.error(e);
let child = child_process.spawn("Rscript", ["./bin/main.R"])
child.stderr.on("data",(d)=>{log.err(d)})
child.stdout.on("data",(d)=>{log.log(d)})
child.stdout.on("close",(d)=>{log.log(d)})
})
但这只适用于第一次调用(在第二次调用时,this
的上下文已更改为 child_process 套接字。我在这里不明白什么?
child.stderr.on("data",log.err)
child.stdout.on("data",log.log)
child.stdout.on("close",log.log)
child.stderr.on("data",log.err)
就像
let err = log.err;
child.stderr.on("data", err)
意味着你正在从 class 中提取一个函数并将其作为回调传递,但是当你像那样提取一个函数时,它将不再将正确的 this
值传递给err
函数调用时。当你这样做时
(d) => log.err(d)
您正在创建一个将正确调用 log.err
的新函数。
另一种方法是您可以这样做
child.stderr.on("data", log.err.bind(this))
或者在你的 class 构造函数中你可以做
this.log = this.log.bind(this);
this.err = this.err.bind(this);
用具有正确this
强制集的实例变量覆盖class原型中的函数,然后
child.stderr.on("data", log.err)
可以正常工作。
我建议您阅读 this
的工作原理,因为这似乎是这个问题的主要触发点。