รู้จักกับ Promise และวิธีการใช้งาน

Sommai Krangpanich
pnpsolution
Published in
2 min readJan 30, 2017

--

ในการเขียนโปรแกรม web application ในปัจจุบันเราต้องมีการยุ่งเกี่ยวกับการเรียกใช้ function ต่างๆ ในระบบ รวมถึงต้องมีการดึงข้อมูลจากฝั่ง server ซึ่งในปัจจุบันการเขียนโปรแกรมเปลี่ยนไปจากเดิมค่อนข้างมาก หากเราใช้ java script หรือ node.js เราก็จะต้องคุ้นเคยกับการเขียนโปรแกรมแบบ asynchronous ขอเรียกย่อๆ ว่า async

ในการเขียนโปรแกรมแบบ async นั้นจะเป็นการทำงานในรูปแบบ none blocking io หรือเอาง่ายๆ ก็คือ ไม่รอกันนั้นเอง โดยในเทคนิคดั้งเดิมที่เขียนกันก็จะใช้หลักการ callback หรือเมื่อเสร็จแล้วให้เรียก function ที่ส่งเข้าไป

ตัวอย่าง ใน Node.JS เมื่อเราต้องการอ่าน file โดยใน node.js จะมีวิธีการอ่าน 2 แบบคือแบบ sync กับ async ดังนี้

วิธีการอ่าน file แบบ syncconst fs = require('fs');
data = fs.readFileSync('message.txt', 'utf8');
console.log(data);
วิธีการอ่าน file แบบ asyncvar fs = require('fs');
fs.readFile('message.txt', 'utf8', function(err, data){
console.log(data);
});

ซึ่งในตัวอย่างการอ่านแบบ async นั้น เราต้องส่ง parameter ไป 3 ตัวนั่นก็คือ ชื่อ file, encoding (ถ้าไม่ระบุเราจะได้ข้อมูลมาเป็น binary) , callback function ซึ่งในนี้จะรับ parameter 2 ตัว คือ err, data (โดยปกติจะนิยมเขียนกันแบบนี้ คือ ตัวแรกเป็น error ถ้าไม่ error ก็จะส่งออกมาเป็น null)

ทีนี้ ถ้าเราต้องการปรับการ read file ให้อยู่ในรูปแบบ function เพื่อเรียกใช้ในระบบได้ เราก็จะได้ code ประมาณนี้

//สร้าง file message.txt ไว้ในเครื่องก่อนนะครับ
//สมมุติว่าใน file มีค่าเป็น hello
var fs = require('fs');function readMessage(callback){
fs.readFile('message.txt', 'utf8', callback);
}
readMessage(function(err, data){
console.log(data);
});
//result = hello

เพื่อให้เห็นภาพอีกนิด สมมุติว่าเราจะเขียน code ให้ทำการ read จาก file message.txt แล้วไป write ใน file out.txt ถ้าเราเขียนในรูปแบบ callback ก็จะได้โปรแกรมหน้าตาประมาณนี้

var fs = require('fs');function readMessage(callback){
fs.readFile('message.txt', 'utf8', callback);
}
function writeMessage(dat, callback){
fs.writeFile('out.txt', dat, callback);
}
readMessage(function(err, data){
writeMessage(data, function(err){
console.log('success');
});
});

อันนี้เราก็จะเห็นว่าถ้ามีการทำงานแบบ waterfall (รอข้อมูลจาก function แรกเพื่อมาทำงานต่อใน function ที่สอง) ก็จะต้องเขียนซ้อนเข้าไปใน callback ซึ่งถ้าการทำงานไม่ยาวมาก็พอได้ แต่ถ้ายาวมาก หรือต้องเสริม logic อื่นเข้าไปก็จะทำให้ทำงานได้ค่อนข้าลำบาก จึงได้มีการเขียนอีกแบบนึง เรียกว่า Promise

ตัว Promise เป็น function ที่เอาไว้แก้ปัญหานั้น โดยถ้าจะได้ Promise ต้อง implement callback ที่รับ parameter 2 ตัวคือ fullfill, reject จาก code ด้านบนถ้าเรามาเขียนใหม่ในรูปแบบ Promise จะได้ดังนี้

var fs = require('fs');function readMessage(){
return new Promise(function (fulfill, reject){
fs.readFile('message.txt', 'utf8', function (err, res){
if (err) reject(err);
else fulfill(res);
});
});
}
function writeMessage(dat){
return new Promise(function (fulfill, reject){
fs.writeFile('out.txt', dat, function (err, res){
if (err) reject(err);
else fulfill(res);
});
});
}
readMessage().then(writeMessage).then(function(){
console.log('success');
});

ตัว Promise เมื่อมีการเรียกจะไม่ต้องส่ง callback function เข้าไปอีกแล้ว เมื่อมีการทำงานใน function นั้นๆ เสร็จ จะเข้ามาที่ then เสมอ ซึ่งถ้าเรามีการทำงานหลายๆ ขั้นตอนก็สามารถส่ง function ตัวถัดไปเข้าไปได้เลย (chianing) ซึ่งก็จะทำให้ code เราสั้นกระชับและไล่โค็ดได้ง่ายขึ้น

สำหรับใครที่จะนำ Promise ไปใช้ project ถ้าเป็น Node.Js สามารถนำไปใช้ได้เลย แต่ถ้าจะไปใช้ในฝั่ง browser ต้องตรวจสอบ browser ที่จะใช้ดังตารางด้านล่างนะครับ

Desktop Version
Mobile Version

--

--