Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Node.js Basics 2017 Handling Errors in Node Handling Status Code Errors

Kenneth Kim
Kenneth Kim
3,795 Points

Another question about the syntax

function printError(error) {
  console.error(error.message);  
} 

const error = "Error Found";
printError(error); // prints 'Error Found'

request.on('error', printError); // prints 'Error Found'

Can someone tell me if node.js events automatically uses the variable in the 1st parameter as input for its callback function located in the 2nd parameter? Because printError() accepts 1 parameter but in request.on('error', printError), it only calls printError().

4 Answers

Thomas Nilsen
Thomas Nilsen
14,957 Points

Short answer: No, the first argument is not used in the 2nd argument (the callback-method)

Also, you wrote:

Because printError() accepts 1 parameter but in request.on('error', printError), it only calls printError()

It doesn't call anything. It only passes the function in to the .on-method, so THAT method can at some point, if needed call it with the appropriate argument.

Look up the concept of callback-methods :)

Here is a simplified example of how an event-emitter in Node might be implemented:

function Emitter() {
    //Object to keep track of the different events that is created. 
    this.events = {}
}

Emitter.prototype.on = function(type, callback) {
    //If the event doesn't exist - we set it to an empty array
    this.events[type] = this.events[type] || [];

    //And add the function we want to call at a later time
    this.events[type].push(callback);
}

Emitter.prototype.emit = function(type) {
    //If the event exists
    if(this.events[type]) {
        //We loop through the array and call all the methods associated with it
        this.events[type].forEach(func => func())
    }
}

//============= Let's test this ===================

//Create a new emitter object
var emitter = new Emitter();


//Create a function to be called on "error"
emitter.on("error", function() {
    console.log("The error happened");
});



//When we emit "error", the method is called
//(added 5 seconds delay here...)
setTimeout(function() {
    emitter.emit("error")
}, 5000);

Hi! I don't understand the line this.events[type].push(callback); because in the line before you wrote that this.events[type] can be either the argument passed or an empty array. If the argument for the Emitter instance then is a string ("error") how can the callback be pushed to a string? Isn't the push method exclusive to arrays? or there is some logic that I am not being aware of? ( just because I am starting javaScript and I want to understand a bit better)

Matthew Caloger
Matthew Caloger
12,903 Points

According to the NodeJS docs:

```The 'error' event may be emitted by a Readable implementation at any time. Typically, this may occur if the underlying stream in unable to generate data due to an underlying internal failure, or when a stream implementation attempts to push an invalid chunk of data.

The listener callback will be passed a single Error object.```

The first parameter of the request.on is the event type to listen for, the second parameter is a callback function that'll get the error object passed to it.

Thomas Nilsen
Thomas Nilsen
14,957 Points

Hi! I don't understand the line this.events[type].push(callback); because in the line before you wrote that this.events[type] can be either the argument passed or an empty array. If the argument for the Emitter instance then is a string ("error") how can the callback be pushed to a string? Isn't the push method exclusive to arrays? or there is some logic that I am not being aware of? ( just because I am starting javaScript and I want to understand a bit better)

I'm not sure I understand the question, but I'll try:

this line right here:

//If the event doesn't exist - we set it to an empty array
this.events[type] = this.events[type] || [];

Let's say we pass "error" as the type (like done in my example).

The we check

this.events["error"] = this.events["error"] || []

Meaning if the object already contains a key named "error" with an array associated with it, we just set it equal to itself, since we don' have to change anything. If the key doesn't exist however, we create it and set it equal an empty array.

So when we get to this line:

this.events[type].push(callback);

we know the event exist. We know the value is an array, so we can push the function we passed in (the callback)

Granted. This example is not at all bulletproof. You can easily pass in wrong types and it doesn't work. This was just an example to demonstrate how an Event-emitter might be implemented.

Thank you for your time. I think I understand it in general, but the only thing that I am still struggling is this part: this.events[type] = this.events[type] which will be converted afterwards into this.events["error"] = this.events["error"]. "Meaning if the object already contains a key named "error" with an array associated with it..." I really can't understand what I marked in bold. Also if I write in the console: var a = {}; a["error"] = a["error"]; //a {error: undefined}. Please, reply just if you think is worthy. because maybe I am not sure if what I am saying is too dumb:)

Thomas Nilsen
Thomas Nilsen
14,957 Points

Thank you for your time. I think I understand it in general, but the only thing that I am still struggling is this part: this.events[type] = this.events[type] which will be converted afterwards into this.events["error"] = this.events["error"]. "Meaning if the object already contains a key named "error" with an array associated with it..." Because if I write in the console: var a = {}; a["error"] = a["error"]; //a {error: undefined}. Please, reply just if you think is worthy. because maybe I am not sure if what I am saying is too dumb:)

If you write

var a = {}; 
a["error"] = a["error"];

You will get an error (or not an error, but the value will be undefined), but not if you write:

var a = {}; 
a["error"] = a["error"] || [];

Now, it will check: do we already have a key named "error"? No? then create it and set it equal to an array. Otherwise, leave the key and value as is.

OK, now think I fully understand!! It is like a verification to see if the property, in this case "error", already exists. As in your example, you haven't written that property beforehand, it will always be set to an empty array. But it is there to prevent that you would overwrite it with an empty array if it already existed. Thank you so much! You gave me light on this!