0

I apologize for the newbness of this question. I'm an experienced programmer but I'm new to javascript. As such I might be using incorrect terminology.

I am trying to write my own middleware handler (as an exercise to better understand the asynchronous approach). I am using a member function called somethingsDone defined on an object named app as a callback that I pass to outside callers. When somethingsDone is called by clients, the value of this inside of it is undefined. Here is the code:

#!/usr/bin/env node

"use strict"

var YAML = require('js-yaml')
var fs = require('fs')

var app = {
  cb_index: 0,
  callbacks: [],
  finished_callback: null,

  use (fn) {
    this.callbacks.push(fn)
  },

  somethingsDone(req) {
    debugger
    // the callback at index this.cb_index is done
    if (this.cb_index == this.callback.count -1) {
      this.finished_callback(req)
    }
    this.cb_index += 1
    this.callbacks[this.cb_index]()
  },

  run (req, done) {
    this.finished_callback = done
    this.callbacks[0](req, this.somethingsDone)
  }
}

app.use((req, next) => {
  fs.readFile(req.filepath, (err, data) => {
    console.log(`Loaded file data from ${req.filepath}: ${data}`)
    req.contents = data
    next()
  })
})

app.use((req, next) => {
  setTimeout(2, () => {
    console.log('Dumping YAML')
    req.yaml = YAML.safeDump(input)
    next()
  })
})

app.use((req, next) => {
  console.log(`YAML data is:\n${req.yaml}`)
})

app.run({ filepath: "/home/ben/docker-compose.json"}, (req) => {
  console.log(`Hey we're finished!  Request data is:\n${req}`)
})

It fails with this error:

/home/ben/js-learning/middleware.js:20
if (this.cb_index == this.callback.count -1) {
        ^

TypeError: Cannot read property 'cb_index' of undefined
    at somethingsDone (/home/ben/js-learning/middleware.js:20:13)
    at /home/ben/js-learning/middleware.js:37:5
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:380:3)

I have tried googling and reading about how this is set in javascript, but I'm not even sure how to search for this (I don't even know what this is called in javascript).

What am I doing wrong? How can I get this to be properly defined when the callback is called?

Freedom_Ben
  • 11,247
  • 10
  • 69
  • 89
  • 1
    `this` refers to the current context. So, when you pass the function as a callback, `this` is referencing the context where it is being called. You might want to look at [closures](http://stackoverflow.com/questions/2070275/javascript-closures-and-callbacks). – Jared Goguen Jan 21 '16 at 06:21
  • You assign `this` to a new variable. http://stackoverflow.com/questions/346015/javascript-closures-and-this – Jasen Jan 21 '16 at 06:21
  • Awesome, thanks guys – Freedom_Ben Jan 21 '16 at 06:24
  • 1
    Using `.bind` would probably the simplest solution here: `this.somethingsDone.bind(this)`. – Felix Kling Jan 21 '16 at 06:26
  • Thanks Felix, I read the answer you linked to and `this.somethingsDone.bind(this)` definitely seems like the easiest solution. – Freedom_Ben Jan 21 '16 at 06:42

0 Answers0