2016年12月15日 星期四

面對 callback function 的 this 問題. 解法: bind

How to bind "this" reference for your callback function
GitHub: example.js
GitHub: example2.js
Googledoc: This document.

(你也可以用 arrow function 解決這個問題)

問題

在 callback function 裡面, this 已經不是 reference 到 parent 物件了. 所以你在 callback function 裡面直接使用 this, 會導致 undefined error.

解法

你必須要在呼叫 callback function 之前, 先把 parent 的 this 參考, 綁到這個 callback function 裡面

Verification

GitHub: example.js
class ABCClass {

 constructor(){
   this.public_mystatus = "OK";   // add a new public member variable

   this.port = 2012;
   this.http = require('http');
   this.server = null;
 }

 createServer(){
   if(this.server == null){
     this.server = this.http.createServer (this.myCallBackFunction.bind(this));
     this.mystatus = "PASS";
   }
 }

 run(){
   this.server.listen(this.port);
   console.log('Server is running');
 }
}

ABCClass.prototype.myCallBackFunction = function (req, res) {
 // 在 callback function 裡面, this 已經不是 parent 物件了.
// 所以你必須要在呼叫 callback function 之前, 先把 parent 的 this 參考, 綁到這個 callback
// function 裡面.

 res.writeHead(200,{'Content-type':'text/plain'});
 res.end('Hello World');
 console.log('this.public_mystatus ', this.public_mystatus); // reference parent's member
}

// Usage
let myABC = new ABCClass();
myABC.createServer();
myABC.run();



E.g.


GitHub: example2.js
class ABCClass {

 constructor(){
   this.public_mystatus = "OK";   // add a new public member variable

   this.port = 2012;
   this.http = require('http');
   this.server = null;
 }

 createServer(){
   if(this.server == null){
     this.server = this.http.createServer( function(req, res) {
 // 在 callback function 裡面, this 已經不是 parent 物件了.
// 所以你必須要在呼叫 callback function 之前, 先把 parent 的 this 參考, 綁到這個 callback
// function 裡面.
      res.writeHead(200,{'Content-type':'text/plain'});
     res.end('Hello World');
     console.log('guest visted');
       console.log('this.public_mystatus ', this.public_mystatus); // reference parent's member
     }.bind(this));
     this.mystatus = "PASS";
   }
 }

 run(){
   this.server.listen(this.port);
   console.log('Server is running');
 }
}


// Usage
let myABC = new ABCClass();
myABC.createServer();
myABC.run();