fetch() ช่วยให้คุณส่งคำขอเครือข่ายที่คล้ายกับ XMLHttpRequest (XHR) ได้ ความแตกต่างหลักคือ Fetch API ใช้ Promises ซึ่งมี API ที่เรียบง่ายกว่าเพื่อช่วยให้คุณหลีกเลี่ยง Callback ที่ซับซ้อนใน XMLHttpRequest API
หากไม่เคยใช้ Promises มาก่อน โปรดดูข้อมูลเบื้องต้นเกี่ยวกับ JavaScript Promises
คำขอดึงข้อมูลพื้นฐาน
ต่อไปนี้คือตัวอย่างการใช้งานด้วย XMLHttpRequest แล้วตามด้วย fetch เราต้องการขอ URL, รับการตอบกลับ และแยกวิเคราะห์เป็น JSON
XMLHttpRequest
XMLHttpRequest ต้องมี Listener 2 รายเพื่อจัดการกรณีที่สำเร็จและกรณีที่เกิดข้อผิดพลาด รวมถึงการเรียกใช้ open() และ send()
ตัวอย่างจากเอกสาร MDN
function reqListener () {
const data = JSON.parse(this.responseText);
console.log(data);
}
function reqError (err) {
console.log('Fetch Error :-S', err);
}
const oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();
ดึงข้อมูล
คำขอดึงข้อมูลของเรามีลักษณะดังนี้
fetch('./api/some.json')
.then(response => {
if (response.status !== 200) {
console.log(`Looks like there was a problem. Status Code: ${response.status}`);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
})
.catch(err => {
console.log('Fetch Error :-S', err);
});
คำขอ fetch() ต้องใช้การเรียกเพียงครั้งเดียวเพื่อทำงานแบบเดียวกับตัวอย่าง XHR ในการประมวลผลการตอบกลับ ก่อนอื่นเราจะตรวจสอบว่าสถานะการตอบกลับคือ 200 จากนั้นแยกวิเคราะห์การตอบกลับเป็น JSON การตอบกลับคำขอ fetch() คือออบเจ็กต์ Stream ซึ่งหมายความว่าหลังจากที่เราเรียกใช้เมธอด json() ระบบจะแสดงผล Promise
สตรีมจะเกิดขึ้นแบบอะซิงโครนัส
ข้อมูลเมตาของคำตอบ
ตัวอย่างก่อนหน้านี้แสดงสถานะของออบเจ็กต์ Response และวิธีแยกวิเคราะห์การตอบกลับเป็น JSON วิธีจัดการข้อมูลเมตาอื่นๆ ที่คุณอาจต้องการเข้าถึง เช่น ส่วนหัว มีดังนี้
fetch('users.json').then(response => {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));
console.log(response.status);
console.log(response.statusText);
console.log(response.type);
console.log(response.url);
});
ประเภทการตอบกลับ
เมื่อเราส่งคำขอดึงข้อมูล การตอบกลับจะได้รับ response.type เป็น "basic", "cors" หรือ "opaque" types เหล่านี้จะแสดงแหล่งที่มาของทรัพยากร และคุณสามารถใช้เพื่อกำหนดวิธีจัดการออบเจ็กต์การตอบกลับได้
เมื่อเบราว์เซอร์ขอทรัพยากรในต้นทางเดียวกัน การตอบกลับจะมีประเภท basic พร้อมข้อจำกัดเกี่ยวกับสิ่งที่คุณดูได้จากการตอบกลับ
หากมีการส่งคำขอทรัพยากรในต้นทางอื่น และต้นทางนั้นแสดงผลส่วนหัว CORS ประเภทจะเป็น cors การตอบกลับ cors จะคล้ายกับการตอบกลับ basic แต่จะจำกัดส่วนหัวที่คุณสามารถดูได้เป็น Cache-Control, Content-Language, Content-Type, Expires, Last-Modified และ Pragma
การตอบกลับ opaque มาจากต้นทางอื่นที่ไม่แสดงส่วนหัว CORS เมื่อมีการตอบกลับแบบทึบ เราจะไม่สามารถอ่านข้อมูลที่แสดงผลหรือดูสถานะของคำขอได้ ซึ่งหมายความว่าคุณจะตรวจสอบไม่ได้ว่าคำขอสำเร็จหรือไม่
คุณสามารถกำหนดโหมดสำหรับคำขอดึงข้อมูลเพื่อให้ระบบแก้ไขเฉพาะคำขอประเภทหนึ่งๆ เท่านั้น โหมดที่คุณตั้งค่าได้มีดังนี้
same-originจะสำเร็จเฉพาะคำขอเนื้อหาในต้นทางเดียวกัน และปฏิเสธคำขออื่นๆ ทั้งหมดcorsอนุญาตคำขอชิ้นงานในต้นทางเดียวกันและต้นทางอื่นๆ ที่แสดงผลส่วนหัว CORS ที่เหมาะสมcors-with-forced-preflightจะทำการตรวจสอบก่อนเที่ยวบินก่อนส่งคำขอno-corsมีไว้เพื่อส่งคำขอไปยังต้นทางอื่นๆ ที่ไม่มีส่วนหัว CORS และส่งผลให้เกิดการตอบกลับopaqueแต่ตามที่ระบุไว้ การดำเนินการนี้ไม่สามารถทำได้ในขอบเขตส่วนกลางของหน้าต่างในขณะนี้
หากต้องการกำหนดโหมด ให้เพิ่มออบเจ็กต์ตัวเลือกเป็นพารามิเตอร์ที่ 2 ในคำขอ fetch และกำหนดโหมดในออบเจ็กต์นั้น ดังนี้
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
.then(response => response.text())
.then(text => {
console.log('Request successful', text);
})
.catch(error => {
log('Request failed', error)
});
การเชื่อมโยง Promise
ฟีเจอร์ที่ยอดเยี่ยมอย่างหนึ่งของ Promise คือความสามารถในการเชื่อมโยงเข้าด้วยกัน สำหรับ fetch() วิธีนี้จะช่วยให้คุณแชร์ตรรกะในคำขอดึงข้อมูลได้
หากทำงานกับ JSON API คุณต้องตรวจสอบสถานะและแยกวิเคราะห์ JSON สำหรับการตอบกลับแต่ละรายการ คุณสามารถลดความซับซ้อนของโค้ดได้โดยกำหนดสถานะและการแยกวิเคราะห์ JSON ในฟังก์ชันแยกต่างหากที่แสดงผล Promise และใช้คำขอ fetch เพื่อจัดการเฉพาะข้อมูลสุดท้ายและกรณีข้อผิดพลาด
function status (response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json (response) {
return response.json()
}
fetch('users.json')
.then(status)
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
}).catch(error => {
console.log('Request failed', error);
});
ตัวอย่างนี้กำหนดฟังก์ชัน status ที่ตรวจสอบ response.status และแสดงผล Promise ที่ได้รับการแก้ไขเป็น Promise.resolve() หรือ Promise ที่ถูกปฏิเสธเป็น Promise.reject()
นี่เป็นเมธอดแรกที่เรียกใช้ในเชน fetch()
หาก Promise แก้ไขได้ สคริปต์จะเรียกใช้เมธอด json() ซึ่งจะแสดงผล Promise รายการที่ 2 จากการเรียกใช้ response.json() และสร้างออบเจ็กต์ที่มี JSON ที่แยกวิเคราะห์แล้ว หากการแยกวิเคราะห์ไม่สำเร็จ ระบบจะปฏิเสธ Promise และเรียกใช้คำสั่ง catch
โครงสร้างนี้ช่วยให้คุณแชร์ตรรกะในคำขอดึงข้อมูลทั้งหมดได้ ซึ่งจะช่วยให้โค้ดดูแลรักษา อ่าน และทดสอบได้ง่ายขึ้น
คำขอ POST
บางครั้งเว็บแอปจำเป็นต้องเรียกใช้ API ด้วยเมธอด POST และรวมพารามิเตอร์บางอย่างไว้ในเนื้อหาของคำขอ โดยตั้งค่าพารามิเตอร์ method และ body ในตัวเลือก fetch() ดังนี้
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
})
.catch(error => {
console.log('Request failed', error);
});
ส่งข้อมูลเข้าสู่ระบบพร้อมคำขอดึงข้อมูล
หากต้องการส่งคำขอดึงข้อมูลพร้อมข้อมูลเข้าสู่ระบบ เช่น คุกกี้ ให้ตั้งค่า credentials ของคำขอเป็น "include" ดังนี้
fetch(url, {
credentials: 'include'
})