Errors & Validation
API ส่วนใหญ่มองความล้มเหลวเป็นช่องทางแยก ไม่ว่าจะเป็น 404, 500 หรือ body ที่ต้องแกะคนละแบบตอนมีอะไรพัง แต่ GraphQL เลือกทางที่ต่างออกไป — response เดียวอธิบายได้ทั้งสิ่งที่สำเร็จและสิ่งที่ล้มเหลว ในรูปร่างเดียว พร้อมกัน รูปร่างนี้แหละคือหัวใจของโมดูลนี้
GraphQL response คือ JSON object ที่มี top-level key ได้มากสุดสามตัว ได้แก่ data, errors และ extensions ตัวแรกเก็บทุกอย่างที่ server resolve สำเร็จ ตัวที่สองคือรายการของทุกอย่างที่พัง สอง key นี้ไม่ได้เลือกได้อย่างใดอย่างหนึ่ง response หนึ่งพก data tree ที่มีข้อมูลเต็ม พร้อมกับ errors array ที่ไม่ว่างมาด้วยกันได้
Errors เป็นส่วนหนึ่งของ contract
หัวข้อที่มีชื่อว่า “Errors เป็นส่วนหนึ่งของ contract”ตลอดคอร์สนี้เราเรียก schema ว่า contract และ errors ก็เขียนอยู่ใน contract นั้นด้วย ตัว spec กำหนดรูปร่างของ error object ไว้ตายตัว กำหนดกฎว่า null โผล่ที่ไหนได้บ้างเมื่อ field หนึ่งล้มเหลว และรับประกันว่าความสำเร็จระดับ transport (HTTP 200) ยังห่อ operation ที่ล้มเหลวไว้ข้างในได้ ฝั่ง client จึงต้องอ่าน errors ไม่ใช่แค่ data
พอซึมซับแนวคิดนี้ได้ มุมมองจะเปลี่ยนไปเลย คุณจะเลิกถามแบบใช่/ไม่ใช่ว่า “request สำเร็จไหม” แล้วหันมาถามว่า “ส่วนไหนสำเร็จ ส่วนไหนพัง และความพังแต่ละอันบอกให้ client ทำอะไรต่อ” GraphQL API ที่ดีตอบทั้งสามคำถามนี้ได้ใน round trip เดียว
รูปร่างของทุก response
หัวข้อที่มีชื่อว่า “รูปร่างของทุก response”flowchart TD Response["GraphQL response (JSON)"] Data["data — what resolved"] Errors["errors — list of failures"] Extensions["extensions — optional metadata"] Response --> Data Response --> Errors Response --> Extensions Errors -->|"path"| Data
ไดอะแกรมแตกออกเป็นสามกิ่ง กิ่ง data สะท้อนรูปร่างของ query กิ่ง errors เป็นรายการแบน ๆ แต่ละ entry ชี้กลับเข้าไปใน data ผ่าน path ส่วน extensions เป็นถุงเปล่าที่ server แนบรายละเอียดแบบเครื่องอ่านได้เข้าไป และเรามีบทเรียนหนึ่งเต็ม ๆ ให้เรื่องนี้
โมดูลนี้ครอบคลุมอะไรบ้าง
หัวข้อที่มีชื่อว่า “โมดูลนี้ครอบคลุมอะไรบ้าง”โมดูลนี้ว่าด้วยด้านความล้มเหลวของ contract ทั้งห้าบทเรียนได้แก่
- Errors & Validation (คุณอยู่ที่นี่) — รูปร่าง response แบบ
data/errorsและทำไม errors ถึงเป็น first-class - GraphQL Errors — เจาะลึก
errorsarray ทั้งmessage,locations,pathและความต่างระหว่าง request errors กับ field errors - Partial Results — nullability คุมการแพร่ของ error อย่างไร และทำไม field พี่น้องยัง resolve ต่อได้แม้ field หนึ่งพัง
- Error Extensions — typed errors ด้วย
extensionsการ throwGraphQLErrorและการซ่อนรายละเอียดภายในบน production - Input Validation — สิ่งที่ schema validate ให้ฟรี เทียบกับ business rule ที่คุณต้องบังคับเองใน resolver
response ที่พก error มาด้วย
หัวข้อที่มีชื่อว่า “response ที่พก error มาด้วย”ทฤษฎีพอแล้ว ตัว runner ด้านล่างนิยาม schema ที่มี field เดียว และ resolver ของ field นั้น throw กด Run แล้วอ่านผลลัพธ์ สังเกตว่า data ยังอยู่ (เป็น null ตรง field ที่พัง) และ errors อธิบายว่าเกิดอะไรขึ้น
อ่าน output เป็น object เดียว ค่า data.currentTrack กลับมาเป็น null เพราะ resolver throw และ field นั้น nullable ถัดมา errors เก็บ entry เดียวที่อธิบายความล้มเหลว ไม่มี key ไหนหักล้างกันเลย การอยู่ร่วมกันแบบนี้แหละที่ทำให้การจัดการ error ของ GraphQL ต่างจาก HTTP status code ธรรมดา