JSはどうやってpromiseにabort機能を追加しますか?


概要
Promiseは三つの状態しかありません。pending、reolve、reject、一つの非同期の承諾がいったん出たら、経歴が待ってから、最終的には成功または失敗のために、途中でキャンセルできません。
promiseにaboort機能を提供する考え方は二つあります。
  • 手動でabortを実現し、キャンセルをトリガした後、非同期で戻ってきたデータを直接廃棄する(手動で実現し、比較的妥当)
  • 原生法AbortControllerを使用して要求を中断する(実験中の方法は互換性があり、ieはサポートしない)
  • aboortを手動で実現する方法には二つのモードがあります。いずれもpromiseに依存するインターフェースが間接的に実現されます。
    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に関する資料は他の関連記事に注目してください。