[Hapi.js ตอนที่ 2] การใช้เชื่อมต่อ และใช้งาน Firebase ใน Hapi.js และ Angular.js
หลังจากที่พูดถึงการใช้งาน Hapi.js ไปแล้ว คราวนี้กลับมาพร้อมกับ Firebase ตามสัญญาครับ
Hapi เป็น framework ตัวหนึ่งที่ทำงานบน Node.js โดยในที่นี้เราจะเอามาไว้สร้าง เซิฟ-เวอร์แล้วให้มันทำหน้าที่เป็นตัว render ไฟล์ html แบบเบื้องต้น
อ่านเพิ่มเติมได้ที่: [Hapi.js ตอนที่ 1] ทำ web/api server ด้วย Hapi.js แทน Express.js ไปแล้ว..
ต่อกันเลยละกันเนาะ 🙂
2.ว่ากันด้วยเรื่องของ Firebase
Firebase คืออะไร? ถ้าเข้าไปอ่านใน wiki มีคำอธิบายไว้ว่า
Firebase is a cloud services provider and backend as a service company.
ซึ่งเอาเข้าจริงแล้วที่เราจะใช้ในรอบนี้มันคือ real time database ซึ่งเป็นส่วนนึงของ service
Firebase’s primary product is a realtime database which provides an API that allows developers to store and sync data across multiple clients.
เอาง่ายๆคือเราจะใช้ firebase ในการเป็น database เก็บข้อมูล ซึ่งในที่นี้คือเก็บข้อมูลลงบนคลาวด์ สิ่งที่ควรรู้อีกอย่างก็คือ firebase มันเป็น noSQL ถ้าเคยใช้ noSQL ตัวอื่นมาก่อนแล้วก้เข้าใจได้ไม่ยาก (เช่น MongoDB, Cassandra, ฯลฯ) คือพวกนี้มันจะไม่เก็บข้อมูลเป็นตาราง แต่มันจะเก็บเป็น key-value pair แทน ซึ่งในเว็บ firebase เองก็บอกไว้ว่าเป็น JSON
Data in your Firebase database is stored as JSON and synchronised in realtime to every connected client.
ก่อนอื่นเราต้องลงทะเบียนสมัครสมาชิกของ firebase ก่อนครับ ถ้าลงทะเบียนแล้วก็ log in เข้าไป ทีนี้เราก็สร้าง app ใหม่ ตรงนี้เลยฮะ
ช่อง name คือเราตั้งชื่อให้กับ app ซึ่งโดยปกติมันจะทำให้ตรงกัน แต่เราจะปรับเองก็ได้ ซึ่งพยายามคิดชื่อให้อย่าซ้ำกับชาวบ้าน
หลังจากกรอกข้อมูลเรียบร้อยเสร็จเราก็จะได้ที่เอาไว้สำหรับเก็บข้อมูลสำหรับโปรเจคเราแล้ว จากนั้นเราก็กด Manage App หลังจากเข้าไปแล้วจะพบว่าข้อมูลมันโล่งเลย “This location is empty!” ซึ่งนั่นก็ถูกแล้ว เพราะเรายังไม่ได้โยนข้อมูลเข้าไปเก็บมันเลย ขั้นต่อไปคือเชื่อม Hapi เข้ากับ Firebase
ก่อนอื่นเลยเราต้องติดตั้ง firebase ก่อน
npm install –save firebase
จากนั้นเราก็ใส่บรรทัดนี้เข้าไปใน server.js เพื่อเป็นการเรียก firebase
const firebase = require('firebase');
ทีนี้เราต้องใส่การอ้างอิงจาก server เราไปยังที่อยู่ของ app ใน firebase ที่เราสร้างไว้ ซึ่งที่จริงแล้วมันจะมีประเด็นเรื่องความปลอดภัยด้วย เพราะการเซ็ตตาม tutorial เป็นไปเพื่อความง่าย ซึ่งทำให้คนอื่นสามารถส่งอะไรเข้าฐานข้อมูลได้ ฉะนั้นถ้าจะทำต่อจริงจังควรศึกษาเรื่องการจัดการกับ security และ rules ด้วย
เราเข้าไปที่ app ที่เราได้สร้างไว้แล้วนำ URL มาใส่ (สมมุติอันนี้ตั้ง name ชื่อ “hfa-article”)
const myFirebaseRef = new firebase("https://hfa-article.firebaseio.com/");
ในส่วน ฟังก์ชัน test อย่างที่เคยบอกไว้ว่ามันเป็นส่วนที่เราจะโยนข้อมูลจาก jsonp เนี่ยลงไปใน database เราก็เขียนโค้ดด้านล่างลงไปใน test การทำงานมันตอนแรกก็ด้วยการสร้างหัวข้อย่อยจากตัว app (สร้าง child นั่นเอง คือเป็น child ของ app) โดยเรากำหนด child สองตัวตามตัวแปรที่เราจะโยนมา จากนั้นเราก็โยนด้วยการใช้ .push จะเห็นว่าเราเอา object ชื่อ parts ที่สร้างไว้ตอนแรกมาโยนเข้าไป (หรือเอาจริงๆจะโยน request.param.temperature ก็ยังได้) โดยโยนเข้าไปในคีย์ “time” (เดี๋ยวไว้มาอธิบายทีหลังว่าทำไมตั้งชื่อนี้)
var tempRef = myFirebaseRef.child("temp");
var humidRef = myFirebaseRef.child("humid");
tempRef.push({"time": parts.temperature});
humidRef.push({"time": parts.humidity});
จากนั้นกด save แล้ว npm start พิมพ์ URL
localhost:3000/10/20/ กด enter
หลังจากมันโผล่มาในหน้าจอแล้วให้ลองไปดูที่ app ใน firebase ของเรา ถ้าไม่มีอะไรผิดพลาดข้อมูลก็ควรจะถูกส่งมาแล้ว
3.Angular + Firebase (ใน client-side)
Angular คือ framework (ไม่ใช่แค่ library ในขณะที่ React, jquery เป็นแค่ library) ตัวหนึ่งที่เอาไว้จัการในส่วน client-side หรือก็คือหน้าเพจเรา มันถูกสร้างมาเพื่อตอบสนองต่อความท้าทายของการทำเว็บแอพซึ่งในยุคปัจจุบันมีแนวโน้มที่หน้าเว็บหนึ่งๆจะมีความซับซ้อนมากขึ้น
“AngularJS (commonly referred to as “Angular” or “Angular.js“) is an open-source web application framework mainly maintained by Google and by a community of individuals and corporations to address many of the challenges encountered in developing single-page applications.” – wikipedia
ส่วนถ้าใครเคยเขียน jQuery มาก่อน ผมแนะนำให้เข้าไปอ่านในนี้ครับ น่าจะทำให้เข้าใจได้ไวขึ้น
“Thinking in AngularJS” if I have a jQuery background?
ขอเกริ่นไว้แค่นี้ก่อนฮะ ถ้าสนใจก็ลองหาอ่านเพิ่มกันดู โอเคเรามาต่อเรื่องของเรากัน ตอนนี้เรามีตัวเก็บข้อมูลแล้ว ระบบหลังบ้านก็พร้อมแล้ว ได้เวลาจับข้อมูลมาแสดง ซึ่งในส่วนนี้เราจะใช้ firebase ทำงานร่วมกับ angular นะฮะ
ก็เปิดไฟล์ index.html ที่เราเอาไปใส่ไว้ในโฟลเดอร์ public ในตอนแรก ซึ่งตอนนี้ยังมีแค่ Hello world อยู่
เพื่อความสะดวกของคนเขียนบทความเองจึงขอยกโค้ดมาทั้งหมดก่อนแล้วไว้อธิบายแยกทีหลัง
จะเห็นว่ามีการกำหนด reference ก่อน
// database reference
var ref = new Firebase("https://hfa-article.firebaseio.com/");
var tempRef = ref.child("temp");
var humidRef = ref.child("humid");
โดยเริ่มจาก ref เป็นการกำหนดตัวอ้างอิงไปยัง url ที่เราได้สร้าง app บน firebase service จากนั้นพวก tempRef และ humidRef เป็นการอ้างอิงไปยังตัวลูก temp และ humid
จากนั้นเราจะไปเรียกข้อมูลมา ซึ่งเท่าที่ดูใน guide ผมต้องการข้อมูลในลักษณะ list อะไรทำนองนั้น จึงต้องเรียก event ที่ชื่อ “child_added“
The
child_added
event is typically used when retrieving a list of items from the database. Unlikevalue
which returns the entire contents of the location,child_added
is triggered once for each existing child and then again every time a new child is added to the specified path.
ซึ่งใช้ร่วมกับ .on สมมุติว่าผมอยากได้ข้อมูลของ temp -> tempRef.on(“child_added”);
ซึ่งจริงๆแค่นี้ก็ใช้งานได้ แต่เพื่อกันเหนียวหรือเพื่อเช็คว่ามีการเรียกข้อมูลเกิดขึ้นจริงหรือมีเออเร่อเกิดขึ้นตรงไหนหรือเปล่า ผมเลยต้องเพิ่มไปสองฟังก์ชัน(callback function) นั่นก็คือ function สำหรับเช็คค่า และ function สำหรับ handle error ดูอันแรกก่อนตรงที่เราใส่ parameter เป็น snapshot ตัวนี้เป็นตัวเอาไว้เช็คว่ามีการส่งค่าเกิดขึ้นจริง ซึ่งต้องใช้ร่วมกับ val() ซึ่งมันจะคืนค่ามาเป็น JavaScript object ของข้อมูลที่เราโยงไว้กับตัวอ้างอิง (ในที่นี้ก็คือ tempRef ซึ่งอ้างอิงไปยังตัวลูก temp ของแอพ hfa-article) เนื่องจากเรามีตัวลูกชื่อ time อยู่ข้างใน temp อีก ตอนพิมพ์ค่าออกมาเราเลยใช้เป็น snapshot.val().time
ฉะนั้นโค้ดที่ได้ออกมาเลยเป็น
tempRef.on("child_added",
function(snapshot) {
console.log(snapshot.val().time);
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
ต่อมาเราจะทำการใส่ Firebase ลงไปใน Angular (ซึ่งตรงนี้จะใส่ได้ เราต้องติดตั้ง AngularFire ซึ่งเราได้ทำการใส่ไปแล้ว ตรง head) โดยตั้งชื่อ app ของ Angular ว่า “sampleApp”
var app = angular.module("sampleApp", ["firebase"]);
ซึ่งหลังจากนี้จะทำให้เราสามารถโยนข้อมูลทีไ่ด้รับจาก tempRef และ humidRef ได้ โดยผ่านทาง $scope และ $firebaseArray (โดย $scope เป็น service ของ Angular เอาไว้จับคู่ข้อมูลแบบ2-way data binding และ firebaseArray เอาไว้แปลง list ข้อมูลที่ได้จาก reference มาเป็น array) ยกตัวอย่าง
$scope.temps = $firebaseArray(tempRef);
จะอธิบายได้ว่า นำข้อมูลที่ได้จาก tempRef (ซึ่งข้อมูลได้เป็น list จาก event ชื่อ “child_added”) ผ่านเข้าไปใน firebaseArray ก่อนที่จะจับมันโยงเข้ากับ $scope.temps ซึ่งตรงนี้จะนำข้อมูลไปจับคู่กับตัวแปร temps ใน HTML (เดี๋ยวเราจะมาอธิบายกันอีกที) – (ดูเพิ่มเติมเรื่อง scope ของ AngularJS)
จากนั้นเราตั้งชื่อส่วน controller ตรงนี้ว่า “sampleCtrl” จะได้โค้ดเป็น
app.controller("sampleCtrl", ["$scope", "$firebaseArray",
function($scope, $firebaseArray) {
$scope.temps = $firebaseArray(tempRef);
$scope.humids = $firebaseArray(humidRef);
}]);
จบจากส่วน script เรามาดูในส่วน body จะเห็นว่ามี attribute คือ ng-app อยู่ ไอ่ตรงนี้มันเอาไว้กำหนดว่าเราจะให้ส่วนไหนใน html อยู่ในขอบเขตของ app บ้าง ซึ่งนั่นก็คือเราจะให้ sampleApp ที่เรากำหนดไว้ทำงานในระดับไหนบ้าง
ng–app : This directive is used to flag the html element that Angular should consider to be the root element of our application. This gives application developers the freedom to tell Angular if the entire html page or only a portion of it should be treated as the Angular application. – angularJS_tutorial
จากนั้นเรามาดูตรง ng-controller นั่นก็คือเรากำลังเรียก controller ที่ชื่อ sampleCtrl เราก็ตามไปดูตรง script ว่ามันทำอะไรบ้าง จะเห็นว่ามันมี scope ที่ตอนนี้มีข้อมูลของ temperature และ humid อยู่ในรูป array เราจะต้องนำมาใช้ต่อ โดยการใช้ ng-repeat โดย “temp in temps” หมายความว่าใน array ที่ชื่อ temps ($scope.temps) เรากำหนดให้ตัวแปร temp แทนตัวลูกแต่ละตัวใน array โดย {{temp.time}} ก็แสดงข้อมูลของ key ที่ชื่อ time (โดยที่ temp ใน {{ }} คือตัวเดียวกับ temp ที่เราตั้งชื่อ ใน “temp in temps”
– เรื่อง ng-controller, ng-repeat อ่านเพิ่มเติมได้ angularJS_tutorial
ซึ่งหากไม่มีอะไรผิดพลาดก็ npm start จากนั้นเข้าไปที่ http://localhost:2000/test จะได้ตาม screenshot