Javascript “this”, “self” object by

29
Dec
0

เราคงจะคุ้นเคยว่าในภาษา OOP ทั่วๆ ไปอย่าง C#, Java นั้นจะมีการใช้งาน this เพื่ออ้างอิงถึงตัว obj ของ class นั้นๆ แต่ว่า this ใน javascript นั้นจะแตกต่างกันออกไป เราลองมาดูตัวอย่าง


var obj = {
items: ["a", "b", "c"],
process: function() {
this.items.forEach(function(item) {
this.print(item);
});
},
print: function(item) {
console.log('*' + item + '*');
}
};
obj.process();

ตัวอย่างนี้เราประกาศตัวแปรชื่อ obj มี properties ชื่อ items และมี function ชื่อ process กับ print เราสั่งให้ทำงานด้วย obj.process() ซึ่งจะเห็นว่ามีการสั่ง this.items.forEach ณ บรรทัดนี้โค้ดจะยังทำงานได้ดังที่เราคาดหวังอยู่ แต่เมื่อเข้ามาอยู่ใน forEach แล้วบรรทัดที่สั่ง this.print(item); ก็ควรจะทำงานได้เหมือน this.items ใช่ไหมครับ แต่เดี๋ยวก่อน! ลอง copy ไปรันใน Google Chrome Developer Tools หรือ Firebug ไหงไม่มีผลลัพธ์ออกมาเลยล่ะ! ลองมาดูที่บรรทัดนี้อีกครั้ง


this.items.forEach(function(item) {
this.print(item);
});

this.items อ้างถึง items จาก function ชื่อ process ได้ แต่ this.print ทำไมสั่งไม่ได้ล่ะ? เป็นเพราะเมื่อมีการประกาศ function(item) {} ซึ่งเป็น function anonymous (ไม่มีชื่อ) ขึ้นมาจะพบว่ามีการสร้าง block ขอบเขตให้ตัวแปร block ใหม่ การประกาศตัวแปรใดๆ ในนี้จะไม่สามารถถูกเรียกจากนอก scope function นี้ได้ใช่ไหมครับ เช่น


this.items.forEach(function(item) {
var a =5;
});
console.log(a);

แน่นอน เราไม่สามารถสั่งการแบบนี้ได้ a จะได้เป็น undefined เช่นเดียวกันกับตัวแปร this ซึ่งตัว javascript จะถือว่าเป็นตัวแปรภายใน scope anonymous function โดยอัตโนมัติ เราไม่ได้เป็นคนประกาศตัวแปรชื่อ this การที่เราสั่ง this.print(item) this นั้นเป็นตัวแปรภายใน scope ที่เราสร้างขึ้นเอง จะไม่สามารถอ้างอิงถึง function print ได้จริงๆ เพราะอยู่คนละ scope กัน ดังนั้น ทีนี้มาดูวิธีแก้ปัญหากันครับ


var self = this;
this.items.forEach(function(item) {
self.print(item);
});

เราจะสร้างตัวแปรชื่อ self มารับค่า this เอาไว้ก่อนเข้าส่วนของ forEach ซึ่งภาษา Javascript นี้สามารถอ้างอิงถึงตัวแปรที่อยู่ภายนอก scope ได้ (ตรงกันข้าม ไม่สามารถอ้างถึงตัวแปรที่อยู่ภายใน scope ที่ลึกกว่าได้ดังที่แสดงให้ดูไปแล้ว เนื่องจาก code ด้านในยังไม่ถูก execute จริงๆ) ทำให้มีตัวแปรที่จำค่า this ของก่อนเข้า forEach เอาไว้ พอมีการอ้างถึง self ซึ่งเก็บว่า this ของ scope ตัวนอกเอาไว้จึงสามารถทำงานได้เป็นปกติครับ เทคนิคนี้ถูกใช้อย่างแพร่หลายมากใน library javascript หลายๆ ตัว ดังนั้นถ้าเจอ self เมื่อไหร่ให้เดาได้เลยว่ามันคือ this ของ scope ตัวนอกครับ :)

Reference: http://book.mixu.net/ch4.html

Socket.IO Socket ที่ใช้ได้ทุก browser by

31
Oct
5

Socket.IO คือ library ตัวหนึ่งซึ่งถูกเขียนขึ้นโดยภาษา NodeJS (Javascript ฝั่ง Server Side) ซึ่งเป็นภาษาใหม่มาแรงในขณะนี้เพราะการทำงานแบบ Asynchronous สามารถทำงานหลายๆ อย่างพร้อมกันแบบ Parallel ได้ (เรียกว่าการเขียนโปรแกรมแบบ Event-driven) เว็บไซต์ที่ใช้งาน Socket.IO เช่น yammer.com, trello.com, c9.io (Cloud9) รวมไปถึงสามารถนำไปใช้ทำเกมประเภท MMORPG ได้ด้วยเช่นกัน

ทำไมต้องใช้ Socket.IO?

  • Support —IE 5.5+, Safari 3+ ,Chrome 4+ , Firefox 3+, Opera 10+
  • Cross domain support
  • ใช้ Websocket เป็น protocol หลัก มีความเร็วในการเชื่อมต่อที่สูงมาก
  • ใช้ง่าย

สาเหตุที่ Socket.IO สามารถใช้งานได้ครอบคลุมทุก browser เป็นเพราะจริงๆ เบื้องหลังของ Socket.IO ใช้รูปแบบการเชื่อมต่อได้หลายรูปแบบ ได้แก่

  1. —WebSocket
  2. Adobe® Flash® Socket
  3. AJAX long polling
  4. AJAX multipart streaming
  5. Forever Iframe
  6. JSONP Polling

หากใช้ตัวแรกไม่ได้ browser ไม่ support ตัว library จะเลื่อนไปใช้ตัวถัดไปโดยอัตโนมัติ และจากในรายการจะเห็นว่ามี AJAX ด้วยซึ่งอย่างที่เราทราบกันวว่าใช้ได้ใน browser แทบทุกตัว จึงเป็นเหตุผลว่าทำไม Socket.IO จึงสามารถใช้งานได้ทุก browser

การ Setup

  • ต้องใช้ NodeJS version ตั้งแต่ 0.4 เป็นต้นไป (ปัจจุบัน 0.8)
  • npm install socket.io

ตัวอย่าง code server

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});

ตัวอย่าง code client


วิธีใส่ SSL Certification (HTTPS) ใน Socket.io (Node.js) by

31
Aug
0

จากการเปิดเกมป๊อกเด้งมาหลายอาทิตย์พบปัญหาคือการติดตั้ง SSL สำหรับ NodeJS นั้นไม่ค่อยจะเหมือนกับภาษาชาวบ้านอื่นๆ ซักเท่าไหร่ครับ ไฟล์ config สำหรับรัน NodeJS นั้นจะไม่ได้เป็นลักษณะเหมือนอย่าง php.ini ซึ่งเป็นไฟล์แยกต่างหากโดยเฉพาะ แต่ NodeJS จะใช้การ config ผ่าน syntax javascript ทั้งหมดครับ (เรียก function เพื่อ setting ค่าต่างๆ ครับ) โดยผมทำเกมบน Facebook จึงต้องติดตั้ง SSL เพื่อให้ใช้งาน HTTPS ได้ ซึ่งองค์ประกอบสำหรับการติดตั้ง SSL 1 domain จะได้แก่

  1. private key file
  2. certificate file ที่ได้จากการซื้อ SSL กับเว็บไซต์ที่รับจดทะเบียน
  3. intermediate file ตามแต่เจ้าของ SSL ที่เราเลือกใช้

แต่ตัวไฟล์ Intermediate ของ SSL นี่สิเจ้าปัญหา เพราะมักเป็น Chain ที่ต่อเนื่องไปยัง Root CA (มี CA หลายชั้นในการตรวจสอบใบอนุญาต SSL ของเรา) ตัวอย่างไฟล์ Intermediate ที่ผมใช้คือ PositiveSSL มีดังนี้ (จริงๆ จะยาวกว่านี้มากนะครับ นี่เป็นเพียงแค่ตัวอย่างลักษณะหน้าตาเฉยๆ )

-----BEGIN CERTIFICATE-----
MIIFKTCCBBGgAwIBAgIRANJ0OUh7t/Gr2RV5gntPmEIwDQYJKoZIhvcNAQEFBQAw
cTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ29tb2RvIENBIExpbWl0ZWQxFzAVBgNV
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFAzCCA+ugAwIBAgIQTM1KmltFEyGMz5AviytRcTANBgkqhkiG9w0BAQUFADCB
lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEhjCCA26gAwIBAgIQUkIGSk83/kNpSHqWZ/9dJzANBgkqhkiG9w0BAQUFADBv
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
...
-----END CERTIFICATE-----

จากที่ยกมาจะเห็นได้ว่ามี —–BEGIN CERTIFICATE—– และ —–END CERTIFICATE—– ทั้งหมด 3 ชุด นั่นคือมีโซ่ทั้งหมด 3 บล็อค (ของคุณอาจมีมากหรือน้อยกว่านี้ตามแต่เจ้า CA ที่คุณจดทะเบียนใช้งาน) ทีนี้สำหรับ Node.js เราต้องแยกไฟล์ intermediate ออกเป็น 3 ไฟล์ (ตามจำนวนบล็อคที่พบ) ไฟล์ละบล็อค แล้วใส่ลงไปใน code ดังนี้ (ใน code ทั้งสามไฟล์จะชื่อ intermediate.pem, intermediate2.pem, intermediate3.pem)


var privateKey = fs.readFileSync('/home/pokdeng/op2-ssl/private.key').toString();
var certificate = fs.readFileSync('/home/pokdeng/op2-ssl/cert.pem').toString();
var ca = fs.readFileSync('/home/pokdeng/op2-ssl/intermediate.pem').toString();
var ca2 = fs.readFileSync('/home/pokdeng/op2-ssl/intermediate2.pem').toString();
var ca3 = fs.readFileSync('/home/pokdeng/op2-ssl/intermediate3.pem').toString();
var ios = require('socket.io').listen(443, {key:privateKey, cert:certificate, ca:[ca,ca2,ca3]});

ใน code ตัวอย่างจะเป็น Socket.IO นะครับ หากเป็นการสร้าง server แบบอื่น (หรือใช้ Framework ใดๆ) parameter ก็จะแตกต่างกันไป แต่ส่วนที่เหมือนกันคือก้อน {key:privateKey, cert:certificate, ca:[ca,ca2,ca3]} ครับ เมื่อใส่แล้วก็ต้องทดสอบว่าเรา setup ได้ถูกต้องหรือยังด้วยการไปที่ http://www.digicert.com/help/ แล้วกรอก URL ที่เรียก Node.js ของเราลงไป (ของผมคือ http://op2.levelup.in.th/socket.io/socket.io.js) หาก setup ได้ถูกต้อง จะปรากฎโซ่คล้องกันต่อเนื่องกันไปพร้อม icon ติ๊กถูก แสดงข้อความว่า “SSL Certificate is correctly installed” ก็เป็นอันเสร็จพิธี!