返回此值的ES6类方法不能被stderr.on调用('data')

时间:2017-04-07 22:34:06

标签: javascript node.js ecmascript-6 es6-class

了解ES6 / NodeJS / JavaScript类的细节。我已经创建了一个日志脚本,我将其传递给child_process。首先,这是日志记录类./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)

1 个答案:

答案 0 :(得分:2)

child.stderr.on("data",log.err)

就像

let err = log.err;
child.stderr.on("data", err)

意味着您正在从类中提取函数并将其作为回调传递,但是当您将函数拉出时,它将不再将正确的this值传递给err函数什么时候叫。当你这样做

(d) => log.err(d)

您正在创建一个能够正确调用log.err的新功能。

替代方案是你可以做

child.stderr.on("data", log.err.bind(this))

或在你的类构造函数中你可以做

this.log = this.log.bind(this);
this.err = this.err.bind(this);

使用具有正确this force-set的实例变量覆盖类原型中的函数,然后执行

child.stderr.on("data", log.err)

会正常工作。

我建议您阅读this的工作原理,因为这似乎是这个问题的主要跳跃点。