มี API ใหม่สำหรับการร้องขอจาก JavaScript: fetch () มีกลไกใด ๆ ในตัวสำหรับการยกเลิกคำขอเหล่านี้ในเที่ยวบินหรือไม่
มี API ใหม่สำหรับการร้องขอจาก JavaScript: fetch () มีกลไกใด ๆ ในตัวสำหรับการยกเลิกคำขอเหล่านี้ในเที่ยวบินหรือไม่
คำตอบ:
fetch
ขณะนี้รองรับsignal
พารามิเตอร์ ณ วันที่ 20 กันยายน 2560 แต่เบราว์เซอร์บางรุ่นอาจไม่รองรับสิ่งนี้ในขณะนี้
2020 UPDATE:เบราว์เซอร์ส่วนใหญ่ที่สำคัญ (ขอบ, Firefox, Chrome, Safari, Opera, และอื่น ๆ ไม่กี่) สนับสนุนคุณลักษณะซึ่งได้กลายเป็นส่วนหนึ่งของมาตรฐานความเป็นอยู่ DOM (ณ วันที่ 5 มีนาคม 2020)
นี่คือการเปลี่ยนแปลงที่เราจะได้เห็นเร็ว ๆ นี้แม้ว่าและดังนั้นคุณควรจะสามารถที่จะยกเลิกการขอโดยใช้sAbortController
AbortSignal
วิธีการทำงานคือ:
ขั้นตอนที่ 1 : คุณสร้างAbortController
(สำหรับตอนนี้ฉันเพิ่งใช้มัน )
const controller = new AbortController()
ขั้นตอนที่ 2 : คุณได้รับAbortController
สัญญาณแบบนี้:
const signal = controller.signal
ขั้นตอนที่ 3 : คุณผ่านการsignal
ดึงข้อมูลเช่น:
fetch(urlToFetch, {
method: 'get',
signal: signal, // <------ This is our AbortSignal
})
ขั้นตอนที่ 4 : เพียงยกเลิกเมื่อใดก็ตามที่คุณต้องการ:
controller.abort();
นี่คือตัวอย่างของวิธีการใช้งาน (ทำงานบน Firefox 57+):
<script>
// Create an instance.
const controller = new AbortController()
const signal = controller.signal
/*
// Register a listenr.
signal.addEventListener("abort", () => {
console.log("aborted!")
})
*/
function beginFetching() {
console.log('Now fetching');
var urlToFetch = "https://httpbin.org/delay/3";
fetch(urlToFetch, {
method: 'get',
signal: signal,
})
.then(function(response) {
console.log(`Fetch complete. (Not aborted)`);
}).catch(function(err) {
console.error(` Err: ${err}`);
});
}
function abortFetching() {
console.log('Now aborting');
// Abort.
controller.abort()
}
</script>
<h1>Example of fetch abort</h1>
<hr>
<button onclick="beginFetching();">
Begin
</button>
<button onclick="abortFetching();">
Abort
</button>
AbortController is not defined
เพราะ อย่างไรก็ตามนี่เป็นเพียงการพิสูจน์แนวคิดอย่างน้อยคนที่มี Firefox 57+ สามารถเห็นมันใช้งานได้
https://developers.google.com/web/updates/2017/09/abortable-fetch
https://dom.spec.whatwg.org/#aborting-ongoing-activities
// setup AbortController
const controller = new AbortController();
// signal to pass to fetch
const signal = controller.signal;
// fetch as usual
fetch(url, { signal }).then(response => {
...
}).catch(e => {
// catch the abort if you like
if (e.name === 'AbortError') {
...
}
});
// when you want to abort
controller.abort();
ทำงานใน edge 16 (2017-10-17), firefox 57 (2017-11-14), desktop safari 11.1 (2018-03-29), ios safari 11.4 (2018-03-29), chrome 67 (2018-05 -29) และใหม่กว่า
บนเบราว์เซอร์รุ่นเก่าคุณสามารถใช้โพลีฟิลของ whatwg-fetchและAbortController polyfill ของ Githubได้ คุณสามารถตรวจสอบเบราว์เซอร์รุ่นเก่าและใช้ polyfills ตามเงื่อนไขได้เช่นกัน:
import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
import {fetch} from 'whatwg-fetch'
// use native browser implementation if it supports aborting
const abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch
ตั้งแต่กุมภาพันธ์ 2018 fetch()
สามารถยกเลิกได้ด้วยรหัสด้านล่างบน Chrome (อ่านโดยใช้ Readable Streamsเพื่อเปิดใช้งานการสนับสนุน Firefox) ไม่มีข้อผิดพลาดเกิดcatch()
ขึ้นในการรับและนี่เป็นวิธีการแก้ปัญหาชั่วคราวจนกว่าAbortController
จะได้รับการยอมรับอย่างเต็มที่
fetch('YOUR_CUSTOM_URL')
.then(response => {
if (!response.body) {
console.warn("ReadableStream is not yet supported in this browser. See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream")
return response;
}
// get reference to ReadableStream so we can cancel/abort this fetch request.
const responseReader = response.body.getReader();
startAbortSimulation(responseReader);
// Return a new Response object that implements a custom reader.
return new Response(new ReadableStream(new ReadableStreamConfig(responseReader)));
})
.then(response => response.blob())
.then(data => console.log('Download ended. Bytes downloaded:', data.size))
.catch(error => console.error('Error during fetch()', error))
// Here's an example of how to abort request once fetch() starts
function startAbortSimulation(responseReader) {
// abort fetch() after 50ms
setTimeout(function() {
console.log('aborting fetch()...');
responseReader.cancel()
.then(function() {
console.log('fetch() aborted');
})
},50)
}
// ReadableStream constructor requires custom implementation of start() method
function ReadableStreamConfig(reader) {
return {
start(controller) {
read();
function read() {
reader.read().then(({done,value}) => {
if (done) {
controller.close();
return;
}
controller.enqueue(value);
read();
})
}
}
}
}
สำหรับตอนนี้ไม่มีวิธีแก้ไขที่เหมาะสมตามที่ @spro พูด
อย่างไรก็ตามหากคุณมีการตอบสนองบนเที่ยวบินและใช้ ReadableStream คุณสามารถปิดสตรีมเพื่อยกเลิกการร้องขอ
fetch('http://example.com').then((res) => {
const reader = res.body.getReader();
/*
* Your code for reading streams goes here
*/
// To abort/cancel HTTP request...
reader.cancel();
});
โพลีฟิลส์:
if(!AbortController){
class AbortController {
constructor() {
this.aborted = false;
this.signal = this.signal.bind(this);
}
signal(abortFn, scope) {
if (this.aborted) {
abortFn.apply(scope, { name: 'AbortError' });
this.aborted = false;
} else {
this.abortFn = abortFn.bind(scope);
}
}
abort() {
if (this.abortFn) {
this.abortFn({ reason: 'canceled' });
this.aborted = false;
} else {
this.aborted = true;
}
}
}
const originalFetch = window.fetch;
const customFetch = (url, options) => {
const { signal } = options || {};
return new Promise((resolve, reject) => {
if (signal) {
signal(reject, this);
}
originalFetch(url, options)
.then(resolve)
.catch(reject);
});
};
window.fetch = customFetch;
}
โปรดทราบว่ารหัสไม่ได้ทดสอบ! แจ้งให้เราทราบหากคุณทำการทดสอบและมีบางอย่างไม่ทำงาน อาจให้คำเตือนว่าคุณพยายามเขียนทับฟังก์ชั่น 'ดึงข้อมูล' จากไลบรารีอย่างเป็นทางการของ JavaScript