Now.js Framework Documentation
คู่มือ HTTP/API - Now.js Framework
คู่มือ HTTP/API - Now.js Framework
คู่มือภาพรวมสำหรับการทำงานกับ HTTP/API ใน Now.js Framework
📋 สารบัญ
- ภาพรวม
- เครื่องมือที่มีให้ใช้งาน
- ตารางเปรียบเทียบ
- เลือกใช้เครื่องมือที่เหมาะสม
- Patterns ทั่วไป
- แนวทางปฏิบัติที่ดี
- ลิงก์ที่เกี่ยวข้อง
ภาพรวม
Now.js Framework มีเครื่องมือหลายตัวสำหรับการทำงานกับ HTTP/API แต่ละตัวออกแบบมาเพื่อจุดประสงค์ที่ต่างกัน ช่วยให้คุณเลือกใช้เครื่องมือที่เหมาะสมกับงานของคุณ
ระดับการใช้งาน
┌─────────────────────────────────────────────────────────┐
│ ApiComponent │ ← UI Layer (ระดับ Component)
│ (Declarative HTML) │
├─────────────────────────────────────────────────────────┤
│ ApiService │ ← Business Logic Layer
│ (Caching, Retry, Deduplication) │ (ระดับ Service)
├─────────────────────────────────────────────────────────┤
│ HttpClient │ ← Low-Level HTTP Layer
│ (http, httpThrow, simpleFetch) │ (ระดับพื้นฐาน)
├─────────────────────────────────────────────────────────┤
│ ResponseHandler │ ← Server Response Layer
│ (Server-driven Actions) │ (ระดับ Response)
└─────────────────────────────────────────────────────────┘เครื่องมือที่มีให้ใช้งาน
1. HttpClient (ระดับพื้นฐาน)
HTTP Client ระดับต่ำที่ใช้ fetch API เป็นพื้นฐาน มี 4 exports หลัก:
HttpClient- Class สำหรับสร้าง instance แบบกำหนดเองhttp- Instance พร้อมใช้ (throwOnError: false)httpThrow- Instance ที่ throw error อัตโนมัติ (throwOnError: true)simpleFetch- Utility function แบบเบา สำหรับการใช้งานง่ายๆ
ใช้เมื่อ:
- ต้องการควบคุมระดับต่ำ (interceptors, CSRF, timeout)
- ทำงานกับ REST API ทั่วไป
- ต้องการความยืดหยุ่นสูง
ไม่ควรใช้เมื่อ:
- ต้องการ caching, retry, deduplication
- ทำงานกับ UI components
- ต้องการ authentication management
📖 อ่านเอกสารฉบับเต็ม: HttpClient
2. ApiService (ระดับ Service)
HTTP Service ระดับสูงที่มีฟีเจอร์ขั้นสูง เหมาะสำหรับ business logic
ฟีเจอร์หลัก:
- ✅ In-memory caching พร้อม expiration
- ✅ Request deduplication (ป้องกันการเรียก API ซ้ำ)
- ✅ Retry mechanism (ลองใหม่อัตโนมัติเมื่อเกิดข้อผิดพลาด)
- ✅ Authentication management (Bearer, Basic, OAuth, Hybrid)
- ✅ Request tracking และ analytics
- ✅ CSRF protection
- ✅ Abort controller management
ใช้เมื่อ:
- ต้องการ caching สำหรับข้อมูลที่ไม่เปลี่ยนแปลงบ่อย
- ต้องการ retry logic สำหรับ network errors
- ทำงานกับ authentication ที่ซับซ้อน
- ต้องการป้องกันการเรียก API ซ้ำในเวลาเดียวกัน
ไม่ควรใช้เมื่อ:
- ต้องการความเรียบง่ายและเบา
- ทำงานกับ real-time data (ไม่ควร cache)
- ไม่ต้องการ retry logic
📖 อ่านเอกสารฉบับเต็ม: ApiService
3. ApiComponent (ระดับ UI)
UI Component wrapper สำหรับการเรียก API แบบ declarative ผ่าน HTML attributes
ฟีเจอร์หลัก:
- ✅ Declarative API calls (กำหนดผ่าน HTML attributes)
- ✅ Autoload support
- ✅ Built-in loading/error/empty states
- ✅ Template rendering
- ✅ Event handlers (onSuccess, onError, onEmpty)
- ✅ Pagination support
- ✅ Polling support
ใช้เมื่อ:
- ต้องการเรียก API จาก UI components
- ต้องการแสดง loading/error states
- ต้องการ render ข้อมูลด้วย templates
- ต้องการ pagination หรือ polling
ไม่ควรใช้เมื่อ:
- ไม่มี UI element
- ต้องการควบคุมระดับต่ำ
- ทำงานกับ business logic ที่ซับซ้อน
📖 อ่านเอกสารฉบับเต็ม: ApiComponent
4. ResponseHandler (ระดับ Response)
Server-driven response handler ที่จัดการ actions จาก server (redirect, alert, script execution, etc.)
ฟีเจอร์หลัก:
- ✅ 17 action types (alert, redirect, script, html, etc.)
- ✅ Server-driven UI updates
- ✅ Auto-integration กับ form submissions
- ✅ Security features (XSS protection, script validation)
ใช้เมื่อ:
- Server ส่ง actions กลับมาพร้อม response
- ต้องการ server-driven UI updates
- ทำงานกับ form submissions
ไม่ควรใช้เมื่อ:
- ต้องการควบคุม UI updates เอง
- ทำงานกับ REST API ทั่วไป
- Server ไม่ส่ง action-based responses
📖 อ่านเอกสารฉบับเต็ม: ResponseHandler
ตารางเปรียบเทียบ
| ฟีเจอร์ | HttpClient | ApiService | ApiComponent | ResponseHandler |
|---|---|---|---|---|
| ระดับการใช้งาน | Low-level | High-level | UI Layer | Response Layer |
| ความซับซ้อน | ⭐️⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️ | ⭐️⭐️ |
| Caching | ❌ | ✅ | ✅ | ❌ |
| Retry Logic | ❌ | ✅ | ✅ | ❌ |
| Deduplication | ❌ | ✅ | ❌ | ❌ |
| Authentication | ⚠️ (Manual) | ✅ | ⚠️ (Via ApiService) | ❌ |
| CSRF Protection | ✅ | ✅ | ⚠️ (Via underlying service) | ❌ |
| Interceptors | ✅ | ✅ | ❌ | ❌ |
| UI Integration | ❌ | ❌ | ✅ | ✅ |
| Template Rendering | ❌ | ❌ | ✅ | ⚠️ (Via HTML action) |
| Loading States | ❌ | ❌ | ✅ | ❌ |
| Pagination | ❌ | ❌ | ✅ | ❌ |
| Polling | ❌ | ❌ | ✅ | ❌ |
| Server Actions | ❌ | ❌ | ❌ | ✅ |
| ขนาดไฟล์ | เล็ก | ใหญ่ | กลาง | เล็ก |
| Performance | เร็ว | กลาง | กลาง | เร็ว |
| Learning Curve | ⭐️⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️ | ⭐️⭐️ |
เลือกใช้เครื่องมือที่เหมาะสม
สถานการณ์ที่ 1: การเรียก API แบบง่าย
ตัวอย่าง: ดึงข้อมูล users จาก API
// ✅ ดีที่สุด: ใช้ simpleFetch (HttpClient)
const users = await simpleFetch.json('/api/users');
console.log(users);
// ✅ ดีที่สุด: ใช้ http (HttpClient)
const response = await http.get('/api/users');
if (response.ok) {
console.log(response.data);
}เหตุผล: ง่าย เบา เร็ว ไม่ต้องการฟีเจอร์ขั้นสูง
สถานการณ์ที่ 2: การเรียก API ที่ต้องการ Caching
ตัวอย่าง: ดึงข้อมูล categories ที่ไม่เปลี่ยนแปลงบ่อย
// ✅ ดีที่สุด: ใช้ ApiService
await ApiService.init({
cache: {
enabled: true,
expiry: { get: 300000 } // Cache 5 นาที
}
});
const categories = await ApiService.get('/api/categories');
console.log(categories.data);เหตุผล: ApiService มี built-in caching พร้อม expiration
สถานการณ์ที่ 3: การเรียก API ที่ต้องการ Authentication
ตัวอย่าง: เรียก protected API endpoint
// ✅ ดีที่สุด: ใช้ ApiService
await ApiService.init({
security: {
bearerAuth: true,
bearerTokenKey: 'auth_token', // Token in localStorage
authStrategy: 'hybrid' // HttpOnly cookie + access token
}
});
const profile = await ApiService.get('/api/user/profile');
console.log(profile.data);เหตุผล: ApiService จัดการ authentication อัตโนมัติ
สถานการณ์ที่ 4: การแสดงข้อมูล API ใน UI
ตัวอย่าง: แสดงรายการ products พร้อม loading state
HTML:
<div data-api-component
data-api-url="/api/products"
data-api-method="GET"
data-api-autoload="true"
data-api-cache="true"
data-api-cache-time="60000">
<template>
<div class="product">
<h3>{{name}}</h3>
<p>{{description}}</p>
<span class="price">{{price}}</span>
</div>
</template>
</div>JavaScript:
// ✅ ดีที่สุด: ใช้ ApiComponent
const component = ApiComponent.create('[data-api-component]');เหตุผล: ApiComponent จัดการ UI states, templates, และ data binding อัตโนมัติ
สถานการณ์ที่ 5: Form Submission พร้อม Server Actions
ตัวอย่าง: Submit form และให้ server กำหนดว่าจะทำอะไรต่อ
HTML:
<form id="loginForm" action="/api/login" method="post">
<input type="email" name="email" required>
<input type="password" name="password" required>
<button type="submit">Login</button>
</form>Server Response:
{
"status": "success",
"message": "Login successful",
"actions": [
{
"action": "alert",
"params": {
"message": "Welcome back!",
"type": "success"
}
},
{
"action": "redirect",
"params": {
"url": "/dashboard",
"delay": 1000
}
}
]
}JavaScript:
// ✅ ดีที่สุด: ใช้ ResponseHandler
// ResponseHandler จะจัดการ form submissions อัตโนมัติ
// และประมวลผล actions จาก serverเหตุผล: ResponseHandler ออกแบบมาสำหรับ server-driven UI updates
สถานการณ์ที่ 6: การเรียก API ที่ต้องการ Retry Logic
ตัวอย่าง: ส่งข้อมูล analytics ที่ต้องการ retry เมื่อ network error
// ✅ ดีที่สุด: ใช้ ApiService
await ApiService.init({
retryCount: 3,
retryDelay: 1000,
connection: {
retryOnNetworkError: true,
retryStatusCodes: [408, 429, 500, 502, 503, 504]
}
});
await ApiService.post('/api/analytics', {
event: 'page_view',
page: '/products'
});เหตุผล: ApiService มี built-in retry mechanism พร้อม exponential backoff
สถานการณ์ที่ 7: การป้องกันการเรียก API ซ้ำ
ตัวอย่าง: ป้องกันการคลิกปุ่มซ้ำๆ ที่ทำให้เรียก API หลายครั้ง
// ✅ ดีที่สุด: ใช้ ApiService
await ApiService.init({
deduplicate: true
});
// ถ้าผู้ใช้คลิกหลายครั้งในเวลาเดียวกัน
// ApiService จะรอ request แรกเสร็จแล้วใช้ผลลัพธ์ร่วมกัน
button.addEventListener('click', async () => {
const result = await ApiService.get('/api/data');
console.log(result);
});เหตุผล: ApiService มี request deduplication built-in
สถานการณ์ที่ 8: การทำงานกับ Interceptors
ตัวอย่าง: เพิ่ม custom headers หรือ logging
// ✅ ดีที่สุด: ใช้ HttpClient
http.addRequestInterceptor(config => {
// เพิ่ม custom header
config.headers['X-App-Version'] = '1.0.0';
// Logging
console.log('Request:', config.method, config.url);
return config;
});
http.addResponseInterceptor(
response => {
console.log('Response:', response.status);
return response;
},
error => {
console.error('Error:', error);
throw error;
}
);
const response = await http.get('/api/data');เหตุผล: HttpClient มี interceptor API ที่ยืดหยุ่น
Patterns ทั่วไป
Pattern 1: Progressive Enhancement
เริ่มจากเครื่องมือที่ง่ายที่สุด แล้วเพิ่มความซับซ้อนเมื่อจำเป็น
// Level 1: การเรียก API แบบง่าย
const users = await simpleFetch.json('/api/users');
// Level 2: ต้องการ caching และ authentication
await ApiService.init({
cache: { enabled: true },
security: { bearerAuth: true }
});
const users = await ApiService.get('/api/users');
// Level 3: ต้องการ UI integration
const component = ApiComponent.create('#userList', {
url: '/api/users',
autoload: true,
cache: true
});Pattern 2: Layer Separation
แยก concerns ตามระดับความรับผิดชอบ
// ❌ ไม่ดี: ทุกอย่างปนกัน
async function loadUserProfile() {
const token = localStorage.getItem('token');
const response = await fetch('/api/user/profile', {
headers: { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
document.getElementById('profile').innerHTML = `
<h1>${data.name}</h1>
<p>${data.email}</p>
`;
}
// ✅ ดี: แยก concerns
// 1. API Layer - ApiService จัดการ HTTP และ auth
await ApiService.init({
security: { bearerAuth: true }
});
// 2. Data Layer - Service function
async function getUserProfile() {
return await ApiService.get('/api/user/profile');
}
// 3. UI Layer - ApiComponent จัดการ rendering
const profileComponent = ApiComponent.create('#profile', {
url: '/api/user/profile',
template: 'profileTemplate'
});Pattern 3: Error Handling Strategy
เลือกกลยุทธ์ error handling ที่เหมาะสม
// Strategy 1: Safe mode (ไม่ throw error)
const response = await http.get('/api/data');
if (!response.ok) {
console.error('Error:', response.statusText);
return;
}
// Strategy 2: Throw mode (throw error)
try {
const response = await httpThrow.get('/api/data');
console.log(response.data);
} catch (error) {
console.error('Error:', error.message);
}
// Strategy 3: Service-level retry
await ApiService.init({
retryCount: 3,
connection: { retryOnNetworkError: true }
});
const response = await ApiService.get('/api/data');Pattern 4: Caching Strategy
เลือกกลยุทธ์ caching ที่เหมาะกับข้อมูล
// Strategy 1: Long-lived data (categories, config)
await ApiService.init({
cache: {
enabled: true,
expiry: { get: 3600000 } // 1 ชั่วโมง
}
});
// Strategy 2: Short-lived data (search results)
await ApiService.init({
cache: {
enabled: true,
expiry: { get: 60000 } // 1 นาที
}
});
// Strategy 3: No cache (real-time data)
await ApiService.init({
cache: { enabled: false }
});
// Strategy 4: Conditional cache
await ApiService.init({
cache: {
enabled: true,
responsePredicate: (response) => {
// Cache เฉพาะ success responses
return response.ok && response.status === 200;
}
}
});แนวทางปฏิบัติที่ดี
1. ✅ เลือกเครื่องมือที่เหมาะสมกับงาน
// ❌ ไม่ดี: ใช้ ApiService สำหรับการเรียก API แบบง่าย
await ApiService.init({ /* many configs */ });
const users = await ApiService.get('/api/users');
// ✅ ดี: ใช้ simpleFetch เมื่อไม่ต้องการฟีเจอร์ขั้นสูง
const users = await simpleFetch.json('/api/users');2. ✅ Initialize services เพียงครั้งเดียว
// ❌ ไม่ดี: Initialize ทุกครั้งที่เรียกใช้
async function fetchData() {
await ApiService.init({ /* config */ });
return await ApiService.get('/api/data');
}
// ✅ ดี: Initialize ครั้งเดียวตอน app start
await ApiService.init({ /* config */ });
async function fetchData() {
return await ApiService.get('/api/data');
}3. ✅ จัดการ errors อย่างเหมาะสม
// ❌ ไม่ดี: ไม่จัดการ error
const response = await http.get('/api/data');
console.log(response.data); // อาจจะเป็น null
// ✅ ดี: ตรวจสอบ response.ok ก่อนใช้ data
const response = await http.get('/api/data');
if (response.ok) {
console.log(response.data);
} else {
console.error('Error:', response.statusText);
}
// ✅ ดีกว่า: ใช้ httpThrow และ try-catch
try {
const response = await httpThrow.get('/api/data');
console.log(response.data);
} catch (error) {
console.error('Error:', error.message);
}4. ✅ ใช้ caching อย่างชาญฉลาด
// ❌ ไม่ดี: Cache ข้อมูลที่เปลี่ยนแปลงบ่อย
await ApiService.init({
cache: {
enabled: true,
expiry: { post: 3600000 } // Cache POST responses?!
}
});
// ✅ ดี: Cache เฉพาะข้อมูลที่เปลี่ยนแปลงไม่บ่อย
await ApiService.init({
cache: {
enabled: true,
expiry: {
get: 300000, // Cache GET 5 นาที
post: 0, // ไม่ cache POST
put: 0, // ไม่ cache PUT
delete: 0 // ไม่ cache DELETE
}
}
});5. ✅ ระบุ content type ที่ถูกต้อง
// ❌ ไม่ดี: ส่ง FormData แต่ระบุ Content-Type
await http.post('/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data' // จะทำให้ boundary หาย
}
});
// ✅ ดี: ปล่อยให้ browser จัดการ Content-Type
await http.post('/api/upload', formData);
// browser จะตั้ง: Content-Type: multipart/form-data; boundary=...6. ✅ ใช้ AbortController สำหรับ long-running requests
// ❌ ไม่ดี: ไม่มีทางยกเลิก request
button.addEventListener('click', async () => {
const response = await http.get('/api/large-data');
});
// ✅ ดี: สามารถยกเลิก request ได้
const controller = new AbortController();
button.addEventListener('click', async () => {
const response = await http.get('/api/large-data', {
signal: controller.signal
});
});
cancelButton.addEventListener('click', () => {
controller.abort();
});7. ✅ ใช้ interceptors สำหรับ cross-cutting concerns
// ❌ ไม่ดี: เพิ่ม token ทุกครั้งที่เรียกใช้
const token = localStorage.getItem('token');
await http.get('/api/data', {
headers: { 'Authorization': `Bearer ${token}` }
});
// ✅ ดี: ใช้ interceptor
http.addRequestInterceptor(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
});
await http.get('/api/data');8. ✅ ใช้ ResponseHandler สำหรับ server-driven flows
// ❌ ไม่ดี: Client กำหนด flow เอง
const response = await http.post('/api/delete-item', { id: 123 });
if (response.ok) {
alert('Deleted successfully');
window.location.reload();
}
// ✅ ดี: ให้ server กำหนด flow
// Server response:
{
"status": "success",
"actions": [
{ "action": "alert", "params": { "message": "Deleted successfully" } },
{ "action": "reload" }
]
}
// ResponseHandler จะจัดการ actions อัตโนมัติ9. ✅ ตั้งค่า timeout ที่เหมาะสม
// ❌ ไม่ดี: Timeout เดียวกันทุก request
http.setTimeout(5000); // 5 วินาทีสำหรับทุก request
// ✅ ดี: Timeout ตามประเภท request
http.setTimeout(30000); // Default 30 วินาที
// สำหรับ long-running requests
await http.post('/api/process-data', data, {
timeout: 120000 // 2 นาที
});
// สำหรับ quick requests
await http.get('/api/ping', {
timeout: 3000 // 3 วินาที
});10. ✅ ใช้ typing และ validation
// ❌ ไม่ดี: ไม่ validate response
const response = await http.get('/api/user');
console.log(response.data.name); // อาจจะ undefined
// ✅ ดี: Validate response ก่อนใช้
const response = await http.get('/api/user');
if (response.ok && response.data) {
const user = response.data;
if (user.name && user.email) {
console.log(user.name);
} else {
console.error('Invalid user data');
}
}ลิงก์ที่เกี่ยวข้อง
เอกสารฉบับเต็ม
- 📖 HttpClient - Low-level HTTP Client
- 📖 ApiService - High-level HTTP Service
- 📖 ApiComponent - UI Component Wrapper
- 📖 ResponseHandler - Server-driven Actions
เอกสารที่เกี่ยวข้อง
- 📖 RouterManager - Client-side Routing
- 📖 FormManager - Form Handling
- 📖 StateManager - State Management
ตัวอย่างการใช้งาน
- 🔗 Examples: Basic HTTP Requests
- 🔗 Examples: Authentication Flows
- 🔗 Examples: Caching Strategies
- 🔗 Examples: Error Handling
สรุป
| ถ้าคุณต้องการ... | ใช้... |
|---|---|
| เรียก API แบบง่าย | simpleFetch หรือ http |
| Caching, Retry, Authentication | ApiService |
| แสดงข้อมูล API ใน UI | ApiComponent |
| Server-driven UI updates | ResponseHandler |
| Interceptors, ความยืดหยุ่นสูง | HttpClient (class) |
กฎทอง: เริ่มจากเครื่องมือที่ง่ายที่สุดที่ทำงานได้ แล้วเพิ่มความซับซ้อนเมื่อจำเป็น