Node.js คือ ตอนที่ 2 : การเขียนโปรแกรมแบบอะซิงโครนัส (Asynchronous Programming)

  1. การเขียนโปรแกรมแบบอะซิงโครนัสคืออะไร
  2. การเขียนโปรแกรมแบบอะซิงโครนัสใน Node.js
    2.1 Callbacks
    2.2 Promises
    2.3 Async/Await
  3. การสร้างแอปพลิเคชัน Web Scraper: การนำไปใช้จริง
  4. การจัดการข้อผิดพลาด

Node.js ได้นำ JavaScript ซึ่งเป็นภาษาของเบราว์เซอร์มาสู่ฝั่งเซิร์ฟเวอร์ ทำให้นักพัฒนามีเครื่องมือในการทำแอพที่ปรับขนาดได้และมีประสิทธิภาพ หนึ่งในหลักการสำคัญของ Node.js คือการเขียนโปรแกรมแบบอะซิงโครนัส ซึ่งเป็นวิธีการทางสถาปัตยกรรมที่เปิดใช้งานการรันโค้ดแบบไม่ปิดกั้นและขับเคลื่อนด้วยเหตุการณ์ บทความนี้มุ่งเจาะลึกโลกของการเขียนโปรแกรมแบบอะซิงโครนัสใน Node.js และแสดงแนวคิดด้วยตัวอย่างที่ใช้งานได้จริงของเว็บแอปพลิเคชัน

1. การเขียนโปรแกรมแบบอะซิงโครนัสคืออะไร

ในรูปแบบการเขียนโปรแกรมแบบซิงโครนัส (Asynchronous) การดำเนินการจะดำเนินการตามลำดับ ทีละรายการ ซึ่งหมายความว่าการดำเนินการจะบล็อกการดำเนินการอื่นๆ ไม่ให้ดำเนินการจนกว่าจะเสร็จสิ้นการดำเนินการ สิ่งนี้อาจกลายเป็นปัญหาคอขวดเมื่อต้องจัดการกับการดำเนินการ I/O เช่น คำขอเครือข่ายหรือการโต้ตอบกับระบบไฟล์ ซึ่งโดยเนื้อแท้แล้วจะใช้เวลานาน

ในทางตรงกันข้าม การเขียนโปรแกรมแบบอะซิงโครนัสช่วยให้การดำเนินการหลายอย่างดำเนินการพร้อมกันโดยไม่ปิดกั้นซึ่งกันและกัน ในบริบทของงาน I/O-bound เช่น การเรียกเครือข่าย การดำเนินการฐานข้อมูล หรือการดำเนินการอ่าน/เขียนไฟล์ สิ่งนี้นำไปสู่การใช้ทรัพยากรระบบอย่างมีประสิทธิภาพมากขึ้นและประสิทธิภาพที่ดีขึ้น

2. การเขียนโปรแกรมแบบอะซิงโครนัสใน Node.js

Node.js สร้างขึ้นจากเอ็นจิ้น V8 JavaScript และใช้โมเดล I/O ที่ขับเคลื่อนด้วยเหตุการณ์และไม่มีการบล็อก ใช้ประโยชน์จากพลังของการเขียนโปรแกรมแบบอะซิงโครนัส (Asynchronous) ผ่านโครงสร้าง เช่น การเรียกกลับ (Callbacks) สัญญา (Promises) และไวยากรณ์ async/await คุณลักษณะเหล่านี้ช่วยให้มั่นใจได้ว่าแอปพลิเคชัน Node.js สามารถจัดการคำขอหลายรายการพร้อมกันได้ ทำให้เหมาะสำหรับงาน I/O จำนวนมากและแอปพลิเคชันแบบเรียลไทม์

2.1 Callbacks

การเรียกกลับ (Callbacks) เป็นฟังก์ชันที่ส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันอื่น และดำเนินการหลังจากฟังก์ชันหลังดำเนินการเสร็จสิ้น แม้ว่าการเรียกกลับเป็นวิธีเดิมในการจัดการความไม่ตรงกันใน JavaScript และ Node.js แต่อาจนำไปสู่ ​​”การเรียกกลับนรก” ซึ่งเป็นสถานการณ์ที่การเรียกกลับซ้อนกันภายในการเรียกกลับ ซึ่งนำไปสู่โค้ดที่อ่านและดีบักได้ยาก

2.2 Promises

มีการแนะนำสัญญา (Promises) เพื่อแก้ปัญหาที่เกี่ยวข้องกับการเรียกกลับ โดยเฉพาะ “callback hell” สัญญาเป็นวัตถุที่แสดงถึงความสมบูรณ์หรือความล้มเหลวของการดำเนินการแบบอะซิงโครนัสในที่สุด อาจอยู่ในสถานะใดสถานะหนึ่งจากสามสถานะ: รอดำเนินการ ดำเนินการแล้ว หรือถูกปฏิเสธ Promises มอบวิธีการที่ตรงไปตรงมามากขึ้นในการจัดการความไม่ตรงกันโดยการผูกมัด.then()และ.catch()วิธีการ ส่งผลให้โค้ดสะอาดและอ่านง่ายขึ้น

2.3 Async/Await

Async/await เป็นส่วนเสริมล่าสุดในคลังโปรแกรมการเขียนโปรแกรมแบบอะซิงโครนัสของ JavaScript async/await สร้างขึ้นบน Promises ให้วิธีการเขียนโค้ดอะซิงโครนัสที่มีลักษณะและการทำงานเหมือนโค้ดซิงโครนัส ฟังก์ชัน async ส่งคืน Promise และ await คีย์เวิร์ดใช้เพื่อหยุดการทำงานของฟังก์ชันชั่วคราวจนกว่า Promise จะได้รับการแก้ไข

3. การทำแอพ Web Scraper: การนำไปใช้จริง

ตอนนี้ มาดูกันว่าเราจะใช้แนวคิดเหล่านี้เพื่อทำแอพการดึงข้อมูลเว็บอย่างง่ายโดยใช้ Node.js ได้อย่างไร แอปจะดึงข้อมูลจากเว็บไซต์และเก็บไว้ในไฟล์

ก่อนเริ่มต้น คุณจะต้องติดตั้ง Node.js ในเครื่องและตั้งค่าโปรเจ็กต์ใหม่โดยใช้ npm (Node Package Manager) สร้างโฟลเดอร์ใหม่ นำทางเข้าไป และเริ่มต้นโปรเจ็กต์ Node.js ใหม่โดยเรียกใช้npm init -y ในเทอร์มินัลของคุณ

ขั้นแรก เราต้องติดตั้ง axios ไลบรารี cheerio และ ซึ่งเราจะใช้สำหรับสร้างคำขอ HTTP และแยกวิเคราะห์ HTML ตามลำดับ

npm install axios cheerio

ตอนนี้มาสร้างไฟล์ชื่อ scraper.js และเริ่มการเขียนโค้ด

// Importing necessary modules
const axios = require('axios');
const cheerio = require('cheerio');
const fs = require('fs').promises; // Built-in module to work with file system

// Define the URL we will be scraping
const url = 'https://example.com';

// Main function to control the flow
async function main() {
try {
const html = await fetchHTML(url);
const data = parseHTML(html);
await saveToFile(data);
console.log('Data saved successfully!');
} catch (error) {
console.error(`Error: ${error}`);
}
}

// Function to fetch HTML of the page
async function fetchHTML(url) {
const response = await axios.get(url);
return response.data;
}

// Function to parse HTML and extract necessary data
function parseHTML(html) {
const $ = cheerio.load(html);
let data = [];

// Logic to extract data goes here, using cheerio's API

return data;
}

// Function to save data to a file
async function saveToFile(data) {
const json = JSON.stringify(data, null, 2);
await fs.writeFile('output.json', json);
}

// Run the main function
main();

ในตัวอย่างนี้ เรากำลังทำตามรูปแบบ async/await ของการจัดการ asynchronicity fetchHTML(url)ส่งคำขอ HTTP GET ไปยัง URL ที่ระบุและรอการตอบกลับกลับมา saveToFile(data)บันทึกข้อมูลที่คัดลอกไปยังไฟล์ในรูปแบบ JSON สังเกตวิธี await การใช้คีย์เวิร์ดเพื่อหยุดการดำเนินการของ async ฟังก์ชันชั่วคราวจนกว่าสัญญาที่ส่งคืนโดยการดำเนินการแบบอะซิงโครนัสจะได้รับการแก้ไข

4. การจัดการข้อผิดพลาด

การจัดการข้อผิดพลาดเป็นสิ่งสำคัญเมื่อเขียนโค้ดแบบอะซิงโครนัส ในตัวอย่างข้างต้น เราใช้ try-catch บล็อกใน main() ฟังก์ชันเพื่อตรวจจับข้อผิดพลาดที่อาจเกิดขึ้นในการดำเนินการแบบอะซิงโครนัส เมื่อเกิดข้อผิดพลาดในการดำเนินการแบบอะซิงโครนัส จะส่งผลให้สัญญาถูกปฏิเสธ คำสัญญาที่ถูกปฏิเสธสามารถติดอยู่ใน catch บล็อกได้


การทำความเข้าใจและเชี่ยวชาญการเขียนโปรแกรมแบบอะซิงโครนัสใน Node.js เป็นทักษะที่สำคัญสำหรับนักพัฒนา JavaScript ทุกคน การเขียนโปรแกรมแบบอะซิงโครนัสช่วยให้ Node.js จัดการการทำงานหลายอย่างพร้อมกันได้ ทำให้เหมาะสำหรับงาน I/O จำนวนมากและแอปพลิเคชันแบบเรียลไทม์ แนวคิดต่างๆ เช่น การเรียกกลับ สัญญา และ async/await นำเสนอวิธีต่างๆ ในการจัดการกับการทำงานแบบอะซิงโครนัส ด้วยการทำแอพการดึงข้อมูลเว็บอย่างง่าย เราได้แสดงให้เห็นว่าแนวคิดเหล่านี้สามารถนำมาใช้ในบริบทที่ใช้งานได้จริงได้อย่างไร


Node.js คืออะไร

Node.js คือ ตอนที่ 1 : โมดูล (Modules)
Node.js คือ ตอนที่ 3 : ระบบเครือข่าย (Networking) และ HTTP