adeniyi Adeosun
adeniyi Adeosun

Reputation: 23

How to control scope in node callbacks?

Playing around i found that the this object across callbacks on the same object stays the same. Is it wise to use this for scope control as follows.

process.stdin.once('data', (chunk) => {
    this.count = 0;
})

process.stdin.on('data', (chunk) => {
    this.count += chunk.length;
});

process.stdin.on('end', () => {
    console.log(`N of bytes ${this.count}`);
});

As I do not see this often, I'm wondering if anything is wrong with it or better methods of doing the same exist.

Upvotes: 2

Views: 69

Answers (2)

Kyle Richardson
Kyle Richardson

Reputation: 5645

It works yes. The reason is you have no exterior closure, and your listeners all use es6 arrow functions so this is never bound to the callbacks. They all reference the global this.

A cleaner way might be to wrap them in a closure and reference a scoped variable.

The IIFE example in @Jamiec's answer would serve your purposes. Just edit the es6 template literal to use ` instead of " as a wrapper as follows:

(function(){
    var count = 0;

    process.stdin.once('data', (chunk) => {
        count = 0;
    })

    process.stdin.on('data', (chunk) => {
        count += chunk.length;
    });

    process.stdin.on('end', () => {
        console.log(`N of bytes ${count}`);
    });    
})()

Upvotes: 2

Jamiec
Jamiec

Reputation: 136239

functions have their own scope, you could use that:

function doSomething(){
    var count = 0;

    process.stdin.once('data', (chunk) => {
        count = 0;
    })

    process.stdin.on('data', (chunk) => {
        count += chunk.length;
    });

    process.stdin.on('end', () => {
        console.log(`N of bytes ${count}`);
    });

}

If there's no need to call this function from elsewhere, and you just want it to execute you could make it an IIFE

(function(){
    var count = 0;

    process.stdin.once('data', (chunk) => {
        count = 0;
    })

    process.stdin.on('data', (chunk) => {
        count += chunk.length;
    });

    process.stdin.on('end', () => {
        console.log(`N of bytes ${count}`);
    });

})()

Note: Edited to correct the wrong char used for templated strings (` not ")

Upvotes: 3

Related Questions