Nội dung

Javascript AJAX, Fetch API

Lợi thế của Javascript (Js) thực sự nổi bật đó là việc tạo, cập nhật, thay đổi, sửa xoá dữ liệu cục bộ mà không phải load lại toàn bộ trang web. Nhưng để đạt được việc đó thì phải cần thời gian cho Javascript tiến hoá. Và hôm nay ta sẽ đi tìm hiểu quá trình này nhé.

AJAX

Trong thời gian xa xưa xây dựng website thì công nghệ sử dụng dựa hoàn toàn vào HTML và mỗi thao tác từ người dùng thì đều phải tải lại trang từ trang chủ. Điều này làm trang web hoạt động kém hiệu quả và trải nghiệm không tốt đối với người dùng làm quá tải máy chủ, tăng băng thông truyền tải, lãng phí tài nguyên.

Vì thế cần phải có một công nghệ nào đó cải thiện việc này. Và AJAX đã ra đời để bù đắp những nhược điểm của web truyền thống.

Cái tên Ajax đã được cha đẻ của nó là ông Jesse James Garrett đưa ra và sử dụng lần đầu vào năm 2005.

Cùng tìm hiểu sâu hơn vào công nghệ này thì

AJAX nghĩa là Asynchronous Javascript And XML

nó không phải là ngôn ngữ lập trình mà là kết hợp các công nghệ với nhau và điểm khác biệt cơ bản với cách truyền thống là với công nghệ này thì nó xử lý thông tin trên máy khách (client) thay vì máy chủ (server) vừa giúp giảm tải cho server lại vừa tăng trải nghiệm của người dùng.

Cụ thể thì nhờ vào việc hoạt động bất đồng bộ asynchronous để xử lý nhiều yêu cầu cùng một lúc dựa vào Javascript, HTML DOM (để hiển thị hoặc sử dụng dữ liệu) và dùng XML để chứa dữ liệu trong quá trình trao đổi nhận và gửi dữ liệu từ trình duyệt web tới máy chủ.

Cụ thể hơn thì ta có hình minh hoạ bên dưới

/javascript-ajax-fetch-api/ajax-and-old-way.jpg
So sánh web truyền thống và ajax
Qua hình ta có thể thấy khác biệt rõ ràng là với cách truyền thống thì với mỗi request từ trình duyệt (client) thì máy chủ phải gửi cả html, css, data cho trình duyệt tải lại trang và hiển thị cho người dùng.

Còn với AJAX thì hai bên trình duyệt vào máy chủ chỉ trao đổi XML data còn lại việc hiển thị lại html, css thì do AJAX đảm nhiệm và hiển nhiên việc này giảm tải cho máy chủ và tiết kiệm băng thông đồng thời tăng trải nghiệm cho người dùng giúp họ thấy việc tương tác với trang web nhanh hơn…

Cũng chính vì sự tiện lợi của AJAX mà chúng ta đã có những React, Angular và Vue 😆

Bây giờ ta đi sâu hơn vào cách hoạt động của AJAX và sau đó sẽ tìm hiểu ví dụ qua code cụ thể sau. Mô tả cụ thể hơn cách AJAX hoạt động

/javascript-ajax-fetch-api/pic_ajax.gif
Cụ thể hơn cách AJAX hoạt động

  1. Một sự kiện xảy ra ở trang web (trang được load, một button được click)
  2. Một XMLHttpRequest object được tạo bởi Javascript
  3. XMLHttpRequest object gửi một request đến web server
  4. Server xử lý request đó
  5. Server gửi response về cho trang web
  6. Response được đọc bởi Javascript
  7. Thực hiện một số hành động trên trang web bằng Javascript (ví dụ như cập nhật lại trang)

Giải thích từ ngữ

XMLHttPRequest

XMLHttpRequest (XHR) là một hàm khởi tạo có sẵn của trình duyệt dùng để giao tiếp với server. XHR cũng là một Web APIs nên nó chỉ có trên môi trường trình duyệt, không có ở Nodejs

Tạo một XMLHttpRequest với cú pháp

1
var xhttp = new XMLHttpRequest()

Một số phương thức của XMLHttpRequest như sau

Phương thức Mô tả
new XMLHttpRequest() Tạo mới XMLHttpRequest object
abort() Hủy request hiện tại
getAllResponseHeaders() Returns tất cả thông tin header
getResponseHeader() Returns thông tin header chỉ định
open(method, url, async, user, psw) Quy định request
method: Loại request (GET, POST, PUT, DELETE)
url: đường dẫn đến server; async: true (bất đồng bộ) hoặc false (đồng bộ)
user: tùy chọn username
psw: tùy chọn password
send(body) Gửi body data đến server. body có thể là; Document, cần serialized trước khi gửi; Blob, BufferSource, FormData, URLSearchParams, or USVString object.null; Nếu không có giá trị nào cho body thì mặc định null được sử dụng.
setRequestHeader() Thêm các giá trị vào trong header request

Một số thuộc tính của XMLHttpRequest

Thuộc tính Mô tả
onreadystatechange Xác định một function được gọi khi thuộc tính readyState thay đổi
readyState Mô tả trạng thái của XMLHttpRequest.
0: request chưa được khởi tạo.
1: kết nối với server được thiết lập.
2: request được server tiếp nhận.
3: đang xử lý request.
4: request kết thúc và response đã sẵn sàng để dùng
responseText Return về response như một string
responseXML Return về response như một XML
status Return về status của request.
200: “OK”.
403: “Forbidden”.
404: “Not Found”.
Xem danh sách đầy đủ tại Http Messages Reference
statusText Return về status dạng text (Ví dụ “OK” hoặc “Not Found”)

Ví dụ XMLHttpRequest

GET

Cùng xem ví dụ dùng XHR để GET request

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function loadDoc(){
  var xhttp = new XMLHttpRequest()
  // function này sẽ chạy mỗi khi readyState thay đổi
  xhttp.onreadystatechange = function () {
    // khi request thành công
    if(this.readyState == 4 && this.status == 200) {
      document.getElementById('demo').innerHTML = this.responseText
      console.log('XMLHttpRequest GET', this.responseText )
    }
    xhttp.open('GET', 'https://httpbin.org/get', true)
    xhttp.send()
  }
  loadDoc()
}
Kết quả trả về là
{ "args": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.9,vi;q=0.8", "Host": "httpbin.org", "Origin": "https://cdpn.io", "Referer": "https://cdpn.io/", "Sec-Ch-Ua": "\"Google Chrome\";v=\"89\", \"Chromium\";v=\"89\", \";Not A Brand\";v=\"99\"", "Sec-Ch-Ua-Mobile": "?0", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "cross-site", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36", "X-Amzn-Trace-Id": "Root=1-60ab2c7e-3c7440b55b69b1dd1eebd0a1" }, "origin": "113.161.70.139", "url": "https://httpbin.org/get" }

POST

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function send() {
  var xhttp = new XMLHttpRequest()
  // function này sẽ chạy mỗi khi readyState thay đổi
  xhttp.onreadystatechange = function () {
    // Khi request thành công
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById('demo').innerHTML = this.responseText
    }
  }
  xhttp.open('POST', 'https://httpbin.org/post', true)
  const body = { name: 'doidev', skill: 'chém gió', point: 100 }
  xhttp.send(JSON.stringify(body))
}
send()
Kết quả trả về là
{ "args": {}, "data": "{\"name\":\"doidev\",\"skill\":\"ch\u00e9m gi\u00f3\",\"point\":100}", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.9,vi;q=0.8", "Content-Length": "50", "Content-Type": "text/plain;charset=UTF-8", "Host": "httpbin.org", "Origin": "https://cdpn.io", "Referer": "https://cdpn.io/", "Sec-Ch-Ua": "\"Google Chrome\";v=\"89\", \"Chromium\";v=\"89\", \";Not A Brand\";v=\"99\"", "Sec-Ch-Ua-Mobile": "?0", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "cross-site", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36", "X-Amzn-Trace-Id": "Root=1-60ab2e24-3340d7973486ab194e6206bf" }, "json": { "name": "doidev", "point": 100, "skill": "ch\u00e9m gi\u00f3" }, "origin": "113.161.70.139", "url": "https://httpbin.org/post" }

Cách dùng AJAX

Dùng XMLHttpRequest

Đây là cách dùng cổ xưa nhất và rườm rà nhất

Dùng Jquery

Cách dùng qua thư viện jQuery cung cấp cho ta nhiều phương thức tiện lợi như load, ajax, get, getJSON

Dùng FetchApi

Fetch API là một cách mà trình duyệt cung cấp, nó nằm mặc định trong trình duyệt và ta chỉ việc sử dụng với nhiều tính năng nâng cao và dễ sử dụng hơn XMLHttpRequest

Dùng axios

Axios, phổ biến nhất, nó là một thư viện chuyên dụng cho việc xử lý AJAX cũng như gọi API. Cung cấp hàng tá tính năng hay, dùng được cho cả môi trường trình duyệt và Node (nếu trình duyệt nó sẽ dựa trên XHR, nếu là Node thì là HTTP interface)

FETCH API

Fetch là một API đơn giản cung cấp cho chúng ta khả năng gửi và nhận request thông qua trình duyệt. Nếu như XMLHttpRequest dùng callback thì Fetch API dùng Promise vì thế sẽ tiện lợi hơn khi thao tác và xử lý. Với Fetch API thì dữ liệu dùng ở đây là dạng JSON và ta cùng đi tìm hiểu về nó một chút.

JSON

JSON (JavaScript Object Notation) là một chuỗi text được viết dưới dạng Javascript Object dùng để lưu trữ và trao đổi dữ liệu.

JSON thường được dùng để lưu trữ string, number, boolean, array, object, null.

Định dạng JSON có thể dễ dàng sử dụng ở các ngôn ngữ lập trình khác nhau. Ở Javascript bạn có thể thao tác với JSON thông qua JSON.parse()JSON.stringify()

Cú pháp JSON

  • Dữ liệu là cặp name:value, name bọc trong dấu nháy kép " "
  • Các cặp dữ liệu được ngăn cách bởi dấu phẩy
  • Ngoặc nhọn mô tả object
  • Ngoặc vuông mô tả mảng

Loại dữ liệu

Trong JSON thì dữ liệu phải là một trong những loại

  • string
  • number
  • object
  • array
  • boolean
  • null

Chuyển Object thành JSON

1
2
3
4
5
6
7
const siteObject = {
  title:'doidev',
  description:'chuyên chém gió',
  size:'1000TB'
}
const siteJSON = JSON.stringify(siteObject)
console.log(siteJSON)

Chuyển JSON thành Object

1
2
3
const siteJSON = `{"title":"doidev","description":"chuyên chém gió","size":"1000TB"}`
const siteObject = JSON.parse(siteJSON)
console.log(siteObject)

Sử dụng Fetch API

Setup

Một setup request được thiết lập đơn giản

1
2
3
fetch('https://example.com/file.json')
  .then((response) => response.json())
  .then((data) => console.log(data))

Lưu ý là Promise return từ fetch() sẽ không reject dựa trên HTTP error status ngay cả khi HTTP 404 hoặc 500. Thay vì đó, nó sẽ resolve bình thường (với ok status là false) và nó chỉ sẻ reject khi mà mạng lỗi hoặc bất cứ điều gì ngăn cản request hoàn thành.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
fetch('https://example.com/file.json')
  .then(function(response) {
    if(!response.ok) {
      throw Error(response.statusText)
    }
    // code cho phần trả về kết quả
  })
  .catch(function(error) {
    console.log('Error nhé: \n', error )
  })

Đọc một response

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
fetch('https://example.com/file.json')
  .then(function(response) {
    if(!response.ok) {
      throw Error(response.statusText)
    }
    // read the response as json
    return respons.json()
  })
  .then(function(responseAsJson) {
    // do logic with JSON
    console.log(responseAsJson)
  })
  .catch(function(error) {
    console.log('Error nè: \n', error)
  })

Mặc định nếu không truyền tham số thứ 2 thì fetch sẽ dùng phương thức GET, còn muốn chỉ rõ phương thức như POST, PUT… thì phải truyền tham số thứ 2 vào. Ví dụ POST

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
async function postData(url = '', data = {}) {
  const response = await fetch (url, {
    method:'POST',//GET, POST, PUT, DELETE, etc.
    mode: 'cors', // no-cors, *cors, same-origin
    cache:'no-cache', // *default, no-cache, reload, force-cache,only-if-cached
    credentials:'same-origin',// include, *same-origin, omit
    headers: {
      'Content-Type': 'application/json' // 'Content-Type': 'application/x-www-form-urlencoded'
    },
    redirect:'follow', // manual, *follow, error
    referencePolicy: 'no-referrer', // no-referrer, * no-referrer-when-downgrade, origin, origin-when-cross-origin,same-origin, strict-origin, strict-origin-when-cross-origin,unsafe-url
    body: JSON.stringify(data) // body data type must match "Content-Type" header
  })
  return response.json() // parses JSON response into native Javascript ojbject
}

postData('https://example.com/file',{file:33})
  .then((data) => {
    console.log(data) // JSON data parsed by 'data.json()' call
  })

Bài này chém cơ bản về AJAX và fetch API, hi vọng qua đó thì ta có một cái hiểu sơ bộ và từ từ tiếp tục tìm hiểu sâu hơn