Now.js Framework Documentation

Now.js Framework Documentation

คู่มือ HTTP/API - Now.js Framework

TH 31 Oct 2025 01:09

คู่มือ HTTP/API - Now.js Framework

คู่มือภาพรวมสำหรับการทำงานกับ HTTP/API ใน Now.js Framework

📋 สารบัญ

  1. ภาพรวม
  2. เครื่องมือที่มีให้ใช้งาน
  3. ตารางเปรียบเทียบ
  4. เลือกใช้เครื่องมือที่เหมาะสม
  5. Patterns ทั่วไป
  6. แนวทางปฏิบัติที่ดี
  7. ลิงก์ที่เกี่ยวข้อง

ภาพรวม

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');
  }
}

ลิงก์ที่เกี่ยวข้อง

เอกสารฉบับเต็ม

เอกสารที่เกี่ยวข้อง

ตัวอย่างการใช้งาน

สรุป

ถ้าคุณต้องการ... ใช้...
เรียก API แบบง่าย simpleFetch หรือ http
Caching, Retry, Authentication ApiService
แสดงข้อมูล API ใน UI ApiComponent
Server-driven UI updates ResponseHandler
Interceptors, ความยืดหยุ่นสูง HttpClient (class)

กฎทอง: เริ่มจากเครื่องมือที่ง่ายที่สุดที่ทำงานได้ แล้วเพิ่มความซับซ้อนเมื่อจำเป็น