ไทย

สำรวจ async context ของ JavaScript และวิธีจัดการตัวแปรที่ผูกกับคำขออย่างมีประสิทธิภาพ เรียนรู้เกี่ยวกับ AsyncLocalStorage, กรณีการใช้งาน, แนวทางปฏิบัติที่ดีที่สุด และทางเลือกอื่นๆ สำหรับการรักษา context ในสภาพแวดล้อมแบบอะซิงโครนัส

JavaScript Async Context: การจัดการตัวแปรที่ผูกกับคำขอ

การเขียนโปรแกรมแบบอะซิงโครนัส (Asynchronous programming) เป็นรากฐานที่สำคัญของการพัฒนา JavaScript สมัยใหม่ โดยเฉพาะในสภาพแวดล้อมอย่าง Node.js ที่ non-blocking I/O มีความสำคัญต่อประสิทธิภาพอย่างยิ่ง อย่างไรก็ตาม การจัดการบริบท (context) ข้ามการทำงานแบบอะซิงโครนัสอาจเป็นเรื่องที่ท้าทาย นี่คือจุดที่ async context ของ JavaScript โดยเฉพาะ AsyncLocalStorage เข้ามามีบทบาท

Async Context คืออะไร?

Async context หมายถึงความสามารถในการเชื่อมโยงข้อมูลกับการทำงานแบบอะซิงโครนัสซึ่งจะคงอยู่ตลอดวงจรชีวิตของการทำงานนั้น สิ่งนี้จำเป็นสำหรับสถานการณ์ที่คุณต้องการรักษาข้อมูลที่ผูกกับคำขอ (request-scoped information) (เช่น ID ผู้ใช้, ID คำขอ, ข้อมูลการติดตาม) ข้ามการเรียกใช้แบบอะซิงโครนัสหลายครั้ง หากไม่มีการจัดการบริบทที่เหมาะสม การดีบัก การบันทึกข้อมูล (logging) และความปลอดภัยอาจทำได้ยากขึ้นอย่างมาก

ความท้าทายในการรักษา Context ในการทำงานแบบอะซิงโครนัส

แนวทางดั้งเดิมในการจัดการบริบท เช่น การส่งผ่านตัวแปรอย่างชัดเจนผ่านการเรียกใช้ฟังก์ชัน อาจกลายเป็นเรื่องยุ่งยากและเกิดข้อผิดพลาดได้ง่ายเมื่อโค้ดแบบอะซิงโครนัสมีความซับซ้อนเพิ่มขึ้น ปัญหา callback ที่ซ้อนกัน (callback hell) และ promise chains สามารถบดบังการไหลของบริบท นำไปสู่ปัญหาในการบำรุงรักษาและช่องโหว่ด้านความปลอดภัยที่อาจเกิดขึ้นได้ ลองพิจารณาตัวอย่างง่ายๆ นี้:


function processRequest(req, res) {
  const userId = req.userId;

  fetchData(userId, (data) => {
    transformData(userId, data, (transformedData) => {
      logData(userId, transformedData, () => {
        res.send(transformedData);
      });
    });
  });
}

ในตัวอย่างนี้ userId ถูกส่งผ่านซ้ำๆ ลงไปใน callback ที่ซ้อนกัน แนวทางนี้ไม่เพียงแต่เยิ่นเย้อ แต่ยังทำให้ฟังก์ชันต่างๆ ผูกมัดกันอย่างแน่นหนา ทำให้การนำกลับมาใช้ใหม่และการทดสอบทำได้ยากขึ้น

ขอแนะนำ AsyncLocalStorage

AsyncLocalStorage เป็นโมดูลที่มีมาในตัวของ Node.js ซึ่งมีกลไกสำหรับจัดเก็บข้อมูลที่เป็นแบบ local สำหรับบริบทอะซิงโครนัสที่เฉพาะเจาะจง ช่วยให้คุณสามารถตั้งค่าและดึงค่าที่ถูกส่งต่อโดยอัตโนมัติข้ามขอบเขตของความเป็นอะซิงโครนัสภายในบริบทการทำงานเดียวกัน สิ่งนี้ช่วยให้การจัดการตัวแปรที่ผูกกับคำขอนั้นง่ายขึ้นอย่างมาก

AsyncLocalStorage ทำงานอย่างไร

AsyncLocalStorage ทำงานโดยการสร้างที่เก็บข้อมูล (storage context) ที่เชื่อมโยงกับการทำงานแบบอะซิงโครนัสในปัจจุบัน เมื่อมีการเริ่มต้นการทำงานแบบอะซิงโครนัสใหม่ (เช่น promise, callback) ที่เก็บข้อมูลนี้จะถูกส่งต่อไปยังการทำงานใหม่โดยอัตโนมัติ สิ่งนี้ทำให้มั่นใจได้ว่าข้อมูลเดียวกันจะสามารถเข้าถึงได้ตลอดทั้งสายของการเรียกใช้แบบอะซิงโครนัส

การใช้งานพื้นฐานของ AsyncLocalStorage

นี่คือตัวอย่างพื้นฐานเกี่ยวกับวิธีการใช้ AsyncLocalStorage:


const { AsyncLocalStorage } = require('async_hooks');

const asyncLocalStorage = new AsyncLocalStorage();

function processRequest(req, res) {
  const userId = req.userId;

  asyncLocalStorage.run(new Map(), () => {
    asyncLocalStorage.getStore().set('userId', userId);

    fetchData().then(data => {
      return transformData(data);
    }).then(transformedData => {
      return logData(transformedData);
    }).then(() => {
      res.send(transformedData);
    });
  });
}

async function fetchData() {
  const userId = asyncLocalStorage.getStore().get('userId');
  // ... ดึงข้อมูลโดยใช้ userId
  return data;
}

async function transformData(data) {
  const userId = asyncLocalStorage.getStore().get('userId');
  // ... แปลงข้อมูลโดยใช้ userId
  return transformedData;
}

async function logData(data) {
  const userId = asyncLocalStorage.getStore().get('userId');
  // ... บันทึกข้อมูลโดยใช้ userId
  return;
}

ในตัวอย่างนี้:

กรณีการใช้งานสำหรับ AsyncLocalStorage

AsyncLocalStorage มีประโยชน์อย่างยิ่งในสถานการณ์ต่อไปนี้:

1. การติดตามคำขอ (Request Tracing)

ในระบบแบบกระจาย (distributed systems) การติดตามคำขอข้ามบริการต่างๆ เป็นสิ่งสำคัญสำหรับการตรวจสอบประสิทธิภาพและระบุคอขวด AsyncLocalStorage สามารถใช้เพื่อจัดเก็บ ID คำขอที่ไม่ซ้ำกันซึ่งจะถูกส่งต่อไปยังบริการต่างๆ สิ่งนี้ช่วยให้คุณสามารถเชื่อมโยง logs และ metrics จากบริการต่างๆ เข้าด้วยกัน ทำให้เห็นภาพรวมการเดินทางของคำขอได้อย่างครอบคลุม ตัวอย่างเช่น ลองพิจารณาสถาปัตยกรรมไมโครเซอร์วิสที่คำขอของผู้ใช้ผ่าน API gateway, บริการยืนยันตัวตน และบริการประมวลผลข้อมูล ด้วยการใช้ AsyncLocalStorage, ID คำขอที่ไม่ซ้ำกันสามารถสร้างขึ้นที่ API gateway และส่งต่อไปยังบริการที่เกี่ยวข้องทั้งหมดในการจัดการคำขอนั้นโดยอัตโนมัติ

2. บริบทการบันทึกข้อมูล (Logging Context)

เมื่อบันทึกเหตุการณ์ต่างๆ การรวมข้อมูลบริบท เช่น ID ผู้ใช้, ID คำขอ หรือ ID เซสชัน มักจะเป็นประโยชน์ AsyncLocalStorage สามารถใช้เพื่อรวมข้อมูลนี้ในข้อความบันทึกโดยอัตโนมัติ ทำให้ง่ายต่อการดีบักและวิเคราะห์ปัญหา ลองนึกภาพสถานการณ์ที่คุณต้องการติดตามกิจกรรมของผู้ใช้ภายในแอปพลิเคชันของคุณ ด้วยการจัดเก็บ ID ผู้ใช้ใน AsyncLocalStorage คุณสามารถรวมข้อมูลนี้ในข้อความบันทึกทั้งหมดที่เกี่ยวข้องกับเซสชันของผู้ใช้นั้นโดยอัตโนมัติ ซึ่งให้ข้อมูลเชิงลึกที่มีค่าเกี่ยวกับพฤติกรรมและปัญหาที่พวกเขาอาจเผชิญ

3. การยืนยันตัวตนและการให้สิทธิ์ (Authentication and Authorization)

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

4. ธุรกรรมฐานข้อมูล (Database Transactions)

เมื่อทำงานกับฐานข้อมูล มักจำเป็นต้องจัดการธุรกรรม (transactions) ข้ามการทำงานแบบอะซิงโครนัสหลายรายการ AsyncLocalStorage สามารถใช้เพื่อจัดเก็บการเชื่อมต่อฐานข้อมูลหรืออ็อบเจกต์ธุรกรรม เพื่อให้แน่ใจว่าการดำเนินการทั้งหมดภายในคำขอเดียวกันจะถูกดำเนินการภายในธุรกรรมเดียวกัน ตัวอย่างเช่น หากผู้ใช้กำลังสั่งซื้อ คุณอาจต้องอัปเดตหลายตาราง (เช่น orders, order_items, inventory) ด้วยการจัดเก็บอ็อบเจกต์ธุรกรรมฐานข้อมูลใน AsyncLocalStorage คุณสามารถมั่นใจได้ว่าการอัปเดตทั้งหมดนี้จะดำเนินการภายในธุรกรรมเดียว ซึ่งรับประกันความเป็นหน่วยเดียว (atomicity) และความสอดคล้องกัน (consistency)

5. การรองรับผู้เช่าหลายราย (Multi-Tenancy)

ในแอปพลิเคชันแบบ multi-tenant การแยกข้อมูลและทรัพยากรสำหรับผู้เช่าแต่ละรายเป็นสิ่งสำคัญ AsyncLocalStorage สามารถใช้เพื่อจัดเก็บ ID ผู้เช่า ช่วยให้คุณสามารถกำหนดเส้นทางคำขอไปยังที่เก็บข้อมูลหรือทรัพยากรที่เหมาะสมแบบไดนามิกตามผู้เช่าปัจจุบัน ลองนึกภาพแพลตฟอร์ม SaaS ที่หลายองค์กรใช้ instance แอปพลิเคชันเดียวกัน ด้วยการจัดเก็บ ID ผู้เช่าใน AsyncLocalStorage คุณสามารถมั่นใจได้ว่าข้อมูลของแต่ละองค์กรจะถูกเก็บแยกจากกันและพวกเขาจะสามารถเข้าถึงได้เฉพาะทรัพยากรของตนเองเท่านั้น

แนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ AsyncLocalStorage

แม้ว่า AsyncLocalStorage จะเป็นเครื่องมือที่ทรงพลัง แต่สิ่งสำคัญคือต้องใช้อย่างรอบคอบเพื่อหลีกเลี่ยงปัญหาด้านประสิทธิภาพที่อาจเกิดขึ้นและรักษาความชัดเจนของโค้ด นี่คือแนวทางปฏิบัติที่ดีที่สุดที่ควรคำนึงถึง:

1. จัดเก็บข้อมูลให้น้อยที่สุด

จัดเก็บเฉพาะข้อมูลที่จำเป็นอย่างยิ่งใน AsyncLocalStorage การจัดเก็บข้อมูลจำนวนมากอาจส่งผลกระทบต่อประสิทธิภาพ โดยเฉพาะอย่างยิ่งในสภาพแวดล้อมที่มีการทำงานพร้อมกันสูง (high-concurrency) ตัวอย่างเช่น แทนที่จะจัดเก็บอ็อบเจกต์ผู้ใช้ทั้งหมด ลองพิจารณาจัดเก็บเฉพาะ ID ผู้ใช้และดึงอ็อบเจกต์ผู้ใช้จากแคชหรือฐานข้อมูลเมื่อจำเป็น

2. หลีกเลี่ยงการสลับบริบทที่มากเกินไป

การสลับบริบทบ่อยครั้งอาจส่งผลกระทบต่อประสิทธิภาพเช่นกัน ลดจำนวนครั้งที่คุณตั้งค่าและดึงค่าจาก AsyncLocalStorage ให้น้อยที่สุด แคชค่าที่เข้าถึงบ่อยไว้ในฟังก์ชันเพื่อลดภาระงานในการเข้าถึงที่เก็บข้อมูลบริบท ตัวอย่างเช่น หากคุณต้องการเข้าถึง ID ผู้ใช้หลายครั้งภายในฟังก์ชัน ให้ดึงข้อมูลจาก AsyncLocalStorage เพียงครั้งเดียวและเก็บไว้ในตัวแปร local เพื่อใช้ในครั้งต่อไป

3. ใช้รูปแบบการตั้งชื่อที่ชัดเจนและสอดคล้องกัน

ใช้รูปแบบการตั้งชื่อที่ชัดเจนและสอดคล้องกันสำหรับคีย์ที่คุณจัดเก็บใน AsyncLocalStorage สิ่งนี้จะช่วยปรับปรุงความสามารถในการอ่านและบำรุงรักษาโค้ด ตัวอย่างเช่น ใช้คำนำหน้าที่สอดคล้องกันสำหรับคีย์ทั้งหมดที่เกี่ยวข้องกับฟีเจอร์หรือโดเมนเฉพาะ เช่น request.id หรือ user.id

4. ทำความสะอาดหลังการใช้งาน

แม้ว่า AsyncLocalStorage จะทำความสะอาดที่เก็บข้อมูลบริบทโดยอัตโนมัติเมื่อการทำงานแบบอะซิงโครนัสเสร็จสมบูรณ์ แต่ก็เป็นแนวปฏิบัติที่ดีที่จะล้างที่เก็บข้อมูลบริบทอย่างชัดเจนเมื่อไม่ต้องการใช้อีกต่อไป สิ่งนี้สามารถช่วยป้องกันหน่วยความจำรั่วไหลและปรับปรุงประสิทธิภาพ คุณสามารถทำได้โดยใช้เมธอด exit เพื่อล้างบริบทอย่างชัดเจน

5. พิจารณาผลกระทบด้านประสิทธิภาพ

ตระหนักถึงผลกระทบด้านประสิทธิภาพของการใช้ AsyncLocalStorage โดยเฉพาะในสภาพแวดล้อมที่มีการทำงานพร้อมกันสูง ทำการวัดประสิทธิภาพ (benchmark) โค้ดของคุณเพื่อให้แน่ใจว่าเป็นไปตามข้อกำหนดด้านประสิทธิภาพของคุณ ทำโปรไฟล์แอปพลิเคชันของคุณเพื่อระบุคอขวดที่อาจเกิดขึ้นที่เกี่ยวข้องกับการจัดการบริบท พิจารณาแนวทางทางเลือก เช่น การส่งผ่านบริบทอย่างชัดเจน หาก AsyncLocalStorage ทำให้เกิดภาระงานด้านประสิทธิภาพที่ยอมรับไม่ได้

6. ใช้ด้วยความระมัดระวังในไลบรารี

หลีกเลี่ยงการใช้ AsyncLocalStorage โดยตรงในไลบรารีที่มีไว้สำหรับการใช้งานทั่วไป ไลบรารีไม่ควรตั้งสมมติฐานเกี่ยวกับบริบทที่กำลังถูกใช้งาน แต่ควรมีตัวเลือกให้ผู้ใช้ส่งผ่านข้อมูลบริบทอย่างชัดเจนแทน สิ่งนี้ช่วยให้ผู้ใช้สามารถควบคุมวิธีการจัดการบริบทในแอปพลิเคชันของตนและหลีกเลี่ยงความขัดแย้งที่อาจเกิดขึ้นหรือพฤติกรรมที่ไม่คาดคิด

ทางเลือกอื่นนอกเหนือจาก AsyncLocalStorage

แม้ว่า AsyncLocalStorage จะเป็นเครื่องมือที่สะดวกและทรงพลัง แต่ก็ไม่ได้เป็นทางออกที่ดีที่สุดสำหรับทุกสถานการณ์เสมอไป นี่คือทางเลือกบางอย่างที่ควรพิจารณา:

1. การส่งผ่านบริบทอย่างชัดเจน (Explicit Context Passing)

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

2. อ็อบเจกต์บริบท (Context Objects)

แทนที่จะส่งผ่านตัวแปรทีละตัว คุณสามารถสร้างอ็อบเจกต์บริบทที่ห่อหุ้มข้อมูลบริบททั้งหมดไว้ ซึ่งจะช่วยให้ลายเซ็นฟังก์ชัน (function signatures) ง่ายขึ้นและทำให้โค้ดอ่านง่ายขึ้น อ็อบเจกต์บริบทเป็นการประนีประนอมที่ดีระหว่างการส่งผ่านบริบทอย่างชัดเจนกับ AsyncLocalStorage โดยเป็นวิธีการจัดกลุ่มข้อมูลบริบทที่เกี่ยวข้องกันไว้ด้วยกัน ทำให้โค้ดเป็นระเบียบและเข้าใจง่ายขึ้น อย่างไรก็ตาม ยังคงต้องมีการส่งผ่านอ็อบเจกต์บริบทไปยังแต่ละฟังก์ชันอย่างชัดเจน

3. Async Hooks (สำหรับการวินิจฉัย)

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

4. Diagnostic Context (OpenTelemetry)

OpenTelemetry มี API ที่เป็นมาตรฐานสำหรับการรวบรวมและส่งออกข้อมูล telemetry รวมถึง traces, metrics และ logs คุณสมบัติ diagnostic context ของมันนำเสนอโซลูชันที่ล้ำหน้าและแข็งแกร่งสำหรับการจัดการการส่งต่อบริบทในระบบแบบกระจาย การผสานรวมกับ OpenTelemetry เป็นวิธีที่เป็นกลางต่อผู้จำหน่าย (vendor-neutral) เพื่อให้แน่ใจว่าบริบทมีความสอดคล้องกันข้ามบริการและแพลตฟอร์มต่างๆ ซึ่งมีประโยชน์อย่างยิ่งในสถาปัตยกรรมไมโครเซอร์วิสที่ซับซ้อนซึ่งบริบทจำเป็นต้องถูกส่งต่อไปยังบริการต่างๆ

ตัวอย่างจากโลกแห่งความเป็นจริง

มาสำรวจตัวอย่างจากโลกแห่งความเป็นจริงว่า AsyncLocalStorage สามารถนำไปใช้ในสถานการณ์ต่างๆ ได้อย่างไร

1. แอปพลิเคชันอีคอมเมิร์ซ: การติดตามคำขอ

ในแอปพลิเคชันอีคอมเมิร์ซ คุณสามารถใช้ AsyncLocalStorage เพื่อติดตามคำขอของผู้ใช้ข้ามบริการต่างๆ เช่น แคตตาล็อกสินค้า ตะกร้าสินค้า และเกตเวย์การชำระเงิน สิ่งนี้ช่วยให้คุณสามารถตรวจสอบประสิทธิภาพของแต่ละบริการและระบุคอขวดที่อาจส่งผลกระทบต่อประสบการณ์ของผู้ใช้


// ใน API gateway
const { AsyncLocalStorage } = require('async_hooks');
const { v4: uuidv4 } = require('uuid');

const asyncLocalStorage = new AsyncLocalStorage();

app.use((req, res, next) => {
  const requestId = uuidv4();
  asyncLocalStorage.run(new Map(), () => {
    asyncLocalStorage.getStore().set('requestId', requestId);
    res.setHeader('X-Request-Id', requestId);
    next();
  });
});

// ในบริการแคตตาล็อกสินค้า
async function getProductDetails(productId) {
  const requestId = asyncLocalStorage.getStore().get('requestId');
  // บันทึก ID คำขอพร้อมกับรายละเอียดอื่นๆ
  logger.info(`[${requestId}] กำลังดึงรายละเอียดสินค้าสำหรับ ID สินค้า: ${productId}`);
  // ... ดึงรายละเอียดสินค้า
}

2. แพลตฟอร์ม SaaS: การรองรับผู้เช่าหลายราย

ในแพลตฟอร์ม SaaS คุณสามารถใช้ AsyncLocalStorage เพื่อจัดเก็บ ID ผู้เช่าและกำหนดเส้นทางคำขอไปยังที่เก็บข้อมูลหรือทรัพยากรที่เหมาะสมแบบไดนามิกตามผู้เช่าปัจจุบัน สิ่งนี้ทำให้มั่นใจได้ว่าข้อมูลของผู้เช่าแต่ละรายจะถูกเก็บแยกจากกันและพวกเขาจะสามารถเข้าถึงได้เฉพาะทรัพยากรของตนเองเท่านั้น


// Middleware เพื่อดึง ID ผู้เช่าจากคำขอ
app.use((req, res, next) => {
  const tenantId = req.headers['x-tenant-id'];
  asyncLocalStorage.run(new Map(), () => {
    asyncLocalStorage.getStore().set('tenantId', tenantId);
    next();
  });
});

// ฟังก์ชันสำหรับดึงข้อมูลสำหรับผู้เช่าที่ระบุ
async function fetchData(query) {
  const tenantId = asyncLocalStorage.getStore().get('tenantId');
  const db = getDatabaseConnection(tenantId);
  return db.query(query);
}

3. สถาปัตยกรรมไมโครเซอร์วิส: บริบทการบันทึกข้อมูล

ในสถาปัตยกรรมไมโครเซอร์วิส คุณสามารถใช้ AsyncLocalStorage เพื่อจัดเก็บ ID ผู้ใช้และรวมไว้ในข้อความบันทึกจากบริการต่างๆ โดยอัตโนมัติ สิ่งนี้ทำให้ง่ายต่อการดีบักและวิเคราะห์ปัญหาที่อาจส่งผลกระทบต่อผู้ใช้รายใดรายหนึ่ง


// ในบริการยืนยันตัวตน
app.use((req, res, next) => {
  const userId = req.user.id;
  asyncLocalStorage.run(new Map(), () => {
    asyncLocalStorage.getStore().set('userId', userId);
    next();
  });
});

// ในบริการประมวลผลข้อมูล
async function processData(data) {
  const userId = asyncLocalStorage.getStore().get('userId');
  logger.info(`[User ID: ${userId}] กำลังประมวลผลข้อมูล: ${JSON.stringify(data)}`);
  // ... ประมวลผลข้อมูล
}

บทสรุป

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

ด้วยการรวมตัวอย่างที่ชัดเจน คำแนะนำเชิงปฏิบัติ และภาพรวมที่ครอบคลุม คู่มือนี้มีจุดมุ่งหมายเพื่อให้นักพัฒนาทั่วโลกมีความรู้ในการจัดการ async context โดยใช้ AsyncLocalStorage ในแอปพลิเคชัน JavaScript ของตนได้อย่างมีประสิทธิภาพ อย่าลืมพิจารณาผลกระทบด้านประสิทธิภาพและทางเลือกอื่นๆ เพื่อให้แน่ใจว่าคุณได้โซลูชันที่ดีที่สุดสำหรับความต้องการเฉพาะของคุณ