JSはどうやってpromiseにabort機能を追加しますか?
概要
Promiseは三つの状態しかありません。pending、reolve、reject、一つの非同期の承諾がいったん出たら、経歴が待ってから、最終的には成功または失敗のために、途中でキャンセルできません。
promiseにaboort機能を提供する考え方は二つあります。手動でabortを実現し、キャンセルをトリガした後、非同期で戻ってきたデータを直接廃棄する(手動で実現し、比較的妥当) 。原生法AbortControllerを使用して要求を中断する(実験中の方法は互換性があり、ieはサポートしない) aboortを手動で実現する方法には二つのモードがあります。いずれもpromiseに依存するインターフェースが間接的に実現されます。
promise race方法
(これは実験中の機能です。DOM規格に属しています。この機能はいくつかのブラウザがまだ開発中です。)AbortControllerインターフェースはコントローラオブジェクトを表しています。必要な時に一つ以上のDOM要求を中止することができます。
以上はJSがpromiseのためにabort機能の詳細を増加しました。JSに関する資料は他の関連記事に注目してください。
Promiseは三つの状態しかありません。pending、reolve、reject、一つの非同期の承諾がいったん出たら、経歴が待ってから、最終的には成功または失敗のために、途中でキャンセルできません。
promiseにaboort機能を提供する考え方は二つあります。
promise race方法
let PromiseWithAbort = function(promise){
let _abort = null;
let Pabort = new Promise((res,rej)=>{
_abort = function(reason ='abort !'){
console.warn(reason);
rej(reason);
}
});
let race = Promise.race([promise,Pabort]);
race.abort = _abort;
console.log(promise,Pabort);
return race;
}
let p1= new Promise(res=>{
setTimeout(()=>{
res('p1 success');
},2000)
})
let testP = PromiseWithAbort(p1);
testP.then(res=>{
console.log('success:',res);
},error=>{
console.log('error:',error);
})
testP.abort();
// : reject: abort!
再包装のpromise
class PromiseWithAbort {
constructor(fn){
let _abort = null;
let _p = new Promise((res,rej)=>{
fn.call(null,res,rej);
_abort = function(error='abort'){ rej(error); }
})
_p.abort = _abort;
return _p;
}
}
let testP = new PromiseWithAbort((res,rej)=>{
setTimeout(() => {
res(1);
},1000);
});
testP.then(r=>{
console.log('res:',r);
},r=>{
console.log('rej:',r);
});
testP.abort();
// : rej: abort
AbortController (これは実験中の機能です。DOM規格に属しています。この機能はいくつかのブラウザがまだ開発中です。)AbortControllerインターフェースはコントローラオブジェクトを表しています。必要な時に一つ以上のDOM要求を中止することができます。
// fetch
let controller = new AbortController();
let signal = controller.signal;
fetch('https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally',{signal}).then(r=>{
console.log(r);
});
controller.abort();
// : Uncaught (in promise) DOMException: The user aborted a request.
// promise
class PromiseWithAbortController {
constructor(fn,{signal}){
if(signal && signal.aborted){
return Promise.reject(new DOMException('Aborted','AbortError'));
}
let _p = new Promise((resolve,reject)=>{
fn.call(null,resolve,reject);
if(signal){
signal.addEventListener('abort',()=>{
reject(new DOMException('Aborted','AbortError'));
})
}
});
return _p;
}
}
let controller = new AbortController();
let signal = controller.signal;
let testP2 = new PromiseWithAbortController((r,j)=>{
setTimeout(() => {
r('success');
}, 1000);
},{signal});
testP2.then(r=>{
console.log('res:',r);
},r=>{
console.log('rej:',r);
});
controller.abort();
// : rej: DOMException: Aborted
Axiosプラグインにはキャンセル機能がついています。
//1. source token
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
//2. function
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
cancel = c;
})
});
// cancel the request
cancel();
// : token
今のプロジェクトで一番頻繁に使われているのはaxiosですので、キャンセルの要求は心配しないでください。dom仕様のAbortControllerは、互換性のため、使用を推奨しません。自分で手を動かして実現するなら、やはり文章の前の二つの方法が妥当です。以上はJSがpromiseのためにabort機能の詳細を増加しました。JSに関する資料は他の関連記事に注目してください。