มาสคอตขนมปังกลมต้นฉบับกำลังเปิดช่องตรวจซองงานที่ปิดผนึกแล้วบนโต๊ะสีมิ้นต์

Bun.peek: อ่าน Promise ที่ settle แล้วโดยไม่สร้าง await boundary ใหม่

พี่โชว์Engineering

บาง integration รู้แน่ว่า Promise ถูก settle ใน tick ก่อนหน้าและต้องอ่านค่าจากโค้ด synchronous ของ runtime นั้น Bun.peek เปิดดูสถานะภายในได้โดยไม่เพิ่ม await boundary ใหม่ครับ แต่ควรใช้เป็นเครื่องมือเฉพาะทาง ไม่ใช่ตัวแทน await ทั่วโปรเจกต์

WHY: ตรวจกล่องที่ปิดแล้ว ไม่ใช่เร่งพนักงานส่งของ

await คือการยอมคืน control ให้ event loop จนงานพร้อม ส่วน peek เหมือนดูช่องหน้ากล่องรับของว่า parcel มาถึงแล้วหรือยัง มันไม่ได้ทำให้ Promise เร็วขึ้น และถ้ายัง pending ผลไม่ได้กลายเป็นค่าธรรมดาอย่างมหัศจรรย์

const answer = Promise.resolve(42);

// เปิดหนึ่งจังหวะให้ microtask ของ Promise.resolve settle ก่อน
await Bun.sleep(0);

const value = Bun.peek(answer);
if (value !== 42) {
  throw new Error(`unexpected value: ${String(value)}`);
}

console.log(value);

กรณี rejected ต้องจัดการอย่างตั้งใจ เพราะการ peek ค่า error ไม่ได้แทน policy ของ unhandled rejection ส่วน Promise ที่ยัง pending อาจคืน object เดิมตามสถานะ runtime ดังนั้นโค้ด production ควรตรวจ status ด้วย API ที่เอกสารระบุ หรือออกแบบให้ฟังก์ชันเป็น async แล้ว await ตามปกติ

ข้อแลกเปลี่ยนใหญ่คือ portability: Bun.peek เป็น Bun-specific ถ้า library ต้องทำงานบน Node.js, Deno และ browser อย่าให้ API นี้ไหลออกไปยังชั้นโดเมน ควรห่อไว้หลัง adapter และมี fallback async ที่ทดสอบร่วมกัน

Recap

  • ใช้เมื่อรู้ lifecycle ของ Promise ชัดและต้องเชื่อม synchronous boundary
  • อย่าคิดว่า peek ทำให้ pending Promise เสร็จเร็วขึ้น
  • กำหนด rejected/unhandled policy เอง
  • ห่อ Bun-specific behavior หลัง adapter เมื่อโค้ดต้อง portable