How JS adds abort function to promise

Time:2022-5-29
catalogue
  • summary
  • Promise race method
  • Repackage promise
  • AbortController 
  • Axios plug-in has its own cancellation function

summary

Promise has only three statuses: pending, resolve, and reject. Once an asynchronous commitment is issued, after waiting, it can only be success or failure, and cannot be canceled halfway.

There are two ways to provide abort function for promise:

  • Manually implement abort. After triggering cancellation, the asynchronously returned data will be directly discarded (manual implementation is more secure)
  • Use the native method abortcontroller to interrupt the request (the method in the experiment is compatible and ie does not support it)

There are two modes to manually implement the abort method: both rely on the promise interface for indirect implementation

Promise race method

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();

//Result: reject: abort!

Repackage 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();
//Result: rej: abort

AbortController 

(this is an experimental function, belonging to the DOM specification. Some browsers are still developing this function.) the abortcontroller interface represents a controller object and allows you to abort one or more DOM requests when necessary.

//Interrupt fetch request
  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();
//Result: uncaught (in promise) domexception: the user aborted a request
//Interrupt a 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();
  //Result: rej: domexception: aborted

Axios plug-in has its own cancellation function

//1 Use the token of source
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 Via outgoing 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();

//Main: requests using the same token can be canceled at the same time

Axios is used most frequently in current projects, so you don’t have to worry about canceling requests. The abortcontroller of DOM specification is not recommended due to compatibility. If you need to implement it yourself, the first two methods in this article are more reliable (promise race method and repackaging promise method).

The above is the details of JS adding abort function to promise. For more information about JS, please follow other developeppaer related articles!