简体   繁体   中英

Node.js Class Module System

I'm trying to create a module/class in node.js to measure asynchronous execution time but do not understand whats wrong with it. I created the following class "Measure.js"

var Measure = module.exports = function(param_timeout, param_cb) {

    this.timeout = param_timeout;
    this.cb = param_cb;
}

Measure.prototype = {
    startDate: "0",
    timeout:"0",
    cb:null,

    start : function() {
        this.startDate = new Date();
        console.log('started');
    },

    stop : function() {
        var stopDate = new Date();
        this.cb(null,(stopDate-this.startDate));
    }
}

I use it with the following code:

var Measure = require('./Measure.js');
measure1 = new Measure(100,function(err,result){console.log('result: ' + result)});
measure1.start();
//do something 
measure1.stop();

and it works just fine. However, if I try this:

var Measure = require('./Measure.js');
measure1 = new Measure(100,function(err,result){console.log('result: ' + result)});
measure1.start();
//do something 
setTimeout(measure1.stop,100);

it doesn't work and throws a TypeError:

TypeError: Object #<Object> has no method 'cb'

Whats wrong with my code?

When you directly call object's method, this inside the method referred to your object, but when you try to use it as argument, this will referred to global object ( global or window ).

In your case better to replace

setTimeout(measure1.stop,100);

with

setTimeout(function() { measure1.stop(); }, 100);

More about this behavior: http://bonsaiden.github.com/JavaScript-Garden/#function.this

The dreaded timeout-switch-context bug strikes again! You see what you see because this object in function called by setTimeout is not measure1 - it's global (= window , when this script is executed in browser). Quoting the MDN :

Code executed by setTimeout() is run in a separate execution context to the function from which it was called. As a consequence, the this keyword for the called function will be set to the window (or global ) object, it will not be the same as the this value for the function that called setTimeout .

It's quite easy to check, by the way:

stop: function() {
  var stopDate = new Date();
  if (! this.cb) { 
    console.log(this); 
  } // *Window*/_display...
}

... and to fix as well:

setTimeout(function() { 
  measure1.stop(); 
}, 100);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM