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()
จะเป็นออบเจ็กต์สตรีม ซึ่งหมายความว่าหลังจากที่เราเรียกเมธอด 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
เหล่านี้แสดงแหล่งที่มาของทรัพยากร และคุณใช้ 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)
});
การผูกมัดตามคำสัญญา
คุณลักษณะที่ยอดเยี่ยมอย่างหนึ่งของคำสัญญาคือความสามารถในการเชื่อมโยงสิ่งต่างๆ เข้าด้วยกัน สำหรับ fetch()
การดำเนินการนี้จะช่วยให้คุณแชร์ตรรกะระหว่างคำขอดึงข้อมูลได้
หากใช้ JSON API คุณจะต้องตรวจสอบสถานะและแยกวิเคราะห์ JSON สําหรับคำตอบแต่ละรายการ คุณลดความซับซ้อนของโค้ดได้โดยกำหนดสถานะและการแยกวิเคราะห์ JSON ในฟังก์ชันแยกต่างหากซึ่งแสดงผล Promise และใช้คำขอการดึงข้อมูลเพื่อจัดการเฉพาะข้อมูลสุดท้ายและกรณีข้อผิดพลาด
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'
})