JS如何为promise增加abort功能

目录

  • 概述
  • promise race方法
  • 重新包装promise
  • AbortController
  • Axios插件自带取消功能

概述 Promise只有三种状态:pending、resolve、reject,一个异步的承诺一旦发出,经历等待(pending)后,最终只能为成功或者失败,中途无法取消(abort)。
为promise提供abort功能的思路有两种:
  • 手动实现abort,触发取消后,异步回来的数据直接丢弃(手动实现,比较稳妥)
  • 使用原生方法AbortController中断请求(实验中的方法,有兼容性,ie不支持)
手动实现abort方法有两种模式:都是依赖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.//中断一个promiseclass 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的tokenconst 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. 通过传出的functionconst CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', {cancelToken: new CancelToken(function executor(c) {// An executor function receives a cancel function as a parametercancel = c; })}); // cancel the requestcancel(); //主要:使用相同token的请求可以一并取消

在现在项目中使用最频繁的是axios,所以取消请求不用担心。dom规范的AbortController,由于兼容性,不推荐使用。如果需要自己动手实现的话,还是文章前两种方法较稳妥(promise race方法和重新包装promise方法)。
【JS如何为promise增加abort功能】以上就是JS为promise增加abort功能的详细内容,更多关于JS的资料请关注脚本之家其它相关文章!

    推荐阅读