สำหรับ Javascript นั้น การทำงานที่เป็น asynchronous เช่น การอ่านข้อมูลจาก MySQL ใน NodeJS เวลาเรารันคำสั่ง SQL ระบบจะรัน คำสั่ง javascript ถัดไปทันที โดยไม่รอให้ MySQL ส่งข้อมูลกลับมาก่อนดังนี้
console.log("1");
mysql_connection.connect(()=>{
mysql_connection.query(sql,place_holder,(err,result)=>{
console.log("2");
});
});
console.log("3");
ผลลัพธ์ที่ได้คือ
1
3
2
เพราะ javascript จะรันคำสั่ง console.log("3"); เลยโดยไม่รอผลลัพธ์ของ
หากเราจำเป็นต้องรันคำสั่ง SQL 2 ครั้ง โดยต้องรอผลจากคำสั่ง SQL แรกต้อทำดังนี้
mysql_connection.connect(()=>{mysql_connection.query(sql,place_holder,(err,result)=>{
......
......
......
mysql_connection.query(sql2,place_holder,(err,result2)=>{
});
});
});
หากมีคำสั่ง SQL ที่ต้องรอผลจาก คำสั่ง SQL ก่อนหน้าเยอะขึ้น จะนำมาซึ่งปัญหา callback hell ซึ่งสามารถ แก้ได้ด้วย การใช้คำสั่ง Promise Async Await ดังตัวอย่างต่อไปนี้
https://github.com/nuntawa/nodejs_mysql_promise_async_await
รับเขียนโปรแกรม NodeJS + MySQL
1. สร้าง NodeJS Project โดย เปิด Command Line และ พิมพ์ md node_mysql เพื่อสร้าง folder พิมพ์ cd node_mysql เพื่อเข้าไปที่ folder และ พิมพ์ npm init -y เพื่อ สร้างไฟล์ package.json
2. install express module และ mysql module
โดย พิมพ์ npm install express --save และ npm install mysql --save
3. เปิด VS Code โดยพิมพ์ code .
โครงสร้าง Database ที่เตรียมไว้คือ
ตาราง product เก็บข้อมูลสินค้า
ตาราง part เก็บอะไหล่ของสินค้า มี unit_count_id เป็น foreign key สำหรับระบุว่า สินค้านี้ใช่หน่วยอะไร
ตาราง unit_count เก็บหน่วยนับ
ตาราง product_part เก็บว่าสินค้าใช้อะไหล่อะไรบ้างจำนวนเท่าไหร่
4. สร้างไฟล์ index.js แล้วพิมพ์ Code ใน visual studio
( Code ดูได้จาก https://github.com/nuntawa/nodejs_mysql_promise_async_await )
var express=require('express');
var app=express();
var port=process.env.PORT || 5000;
var mysql = require('mysql');
//กำหนด Host และ Username Password ของ MySQL
var mysql_connection = mysql.createConnection
host: "localhost",
user: "root",
password: "",
database: "factory"
});
//สร้าง Function สำหรับ เชื่อมต่อ MySQL โดย รับค่าคำสั่ง sql และค่าของตัวแปรอยู่ใน place_holder ( เพื่อป้องกัน SQL Injection )
var get_mysql_data=(sql,place_holder)=>
{
//กำหนดให้ return object Promise รอ
return new Promise(function(resolve, reject){
mysql_connection.connect(()=>{
//รันคำสั่ง SQL
mysql_connection.query(sql,place_holder,(err,result)=>{
if(err)
{
console.log(err);
return reject(err);
}
if(result==null)
{
return reject({message:"Mysql Error"});
}
//ส่งผลลัพธืของคำสั่ง sql กลับไปให้ทำงานต่อ
resolve(result);
})
});
});
}
//กำหนด Route
app.get('/', async (req, res)=>{
var product;
try{
//ให้รอผลจากคำสั่ง SQL SELECT * FROM product ก่อนค่อยทำงานในคำสั่งถัดไป ( ทำงานแบบ synchronous )
product= await get_mysql_data("SELECT * FROM product");
}catch(err)
{
console.log(err);
}
//เมื่อได้ข้อมูลในตาราง Product แล้วเราจะเอามา part ของแต่ละ product
for(var i=0;i<product.length;i++)
{
try{
var sql=`SELECT part_name,product_part.qty,unit_count_name FROM
part INNER JOIN product_part ON part.part_id=product_part.part_id
INNER JOIN unit_count ON unit_count.unit_count_id=part.unit_count_id
WHERE (product_id=?)`;
var part= await get_mysql_data(sql,[product[i].product_id]);
product[i]["part"]=part;
}
catch(err)
{
console.log(err);
}
}
var html="";
for(var i=0;i<product.length;i++)
{ //แสดงชื่อ product
html+="<h4>"+product[i].product_name+"<h4>";
html+="<ul>";
product[i].part.forEach(part_item => {
//แสดง part และจำนวนที่ใช้ของแต่ละ product
html+="<li>"+part_item.part_name+" จำนวน "+part_item.qty+" "+part_item.unit_count_name+"</li>";
});
html+="</ul>";
html+="<hr />";
}
res.send(html);
});
//กรณีไม่พบหน้า
app.get('*', (req, res)=>{
res.status(404).send('Page Not Found');
});
app.listen(port);
console.log("server start");
ไปที่ ComandLine และพิมพ์ node index ผลลัพธ์ที่ได้คือ