如何更好的取消一个promise?

简介: 一个正在执行中的promise怎样被取消?其实就像一个执行中的ajax要被取消一样,ajax有abort()进行取消,而且fetch api 也有了相关的规范-【AbortController】。

一个正在执行中的promise怎样被取消?

其实就像一个执行中的ajax要被取消一样,ajax有abort()进行取消,而且fetch api 也有了相关的规范-【AbortController】。

fetch 怎样取消?


先来看下如何取消一个fetch请求

const url = "https://bigerfe.com/api/xxxx"
let controller;
let signal;
function requestA(){
 if (controller !== undefined) {
        controller.abort(); //终止请求
    }
    if ("AbortController" in window) {
        controller = new AbortController;
        signal = controller.signal;
    }
    fetch(url, {signal})
        .then((response) => {
            //do xxx
            updateAutocomplete()
        })
        .catch((error) => {
            //do xxx
            handleError(error);
        })
    });
}

怎样实现实现promise的取消?


方案1 - 借助reject 方法

我们都知道一个promise对象状态的改变是通过resolve和reject来执行的。那是不是可以借助reject方法来模拟呢?

上代码

//返回一个promise和abort方法
function getPromise() {
  let _res, _rej;
  const promise = new Promise((resolve, reject) => {
    _res = resolve;
    _rej = reject;
    setTimeout(() => {
      resolve('123')
    }, 5000);
  });
  return {
    promise,
    abort: () => {
      _rej({
        name: "abort",
        message: "the promise is aborted",
        aborted: true,
      });
    }
  };
}
const { promise, abort } = getPromise();
promise.then(console.log).catch(e => {
  console.log(e);
});
abort();

上面的方法可以正常执行,但是不够通用,可以将Promise构造函数内的逻辑提取出来,作为一个回调传进去。

改造一下

function getPromise(cb) {
  let _res, _rej;
  const promise = new Promise((res, rej) => {
    _res = res;
    _rej = rej;
    cb && cb(res,rej);
  });
  return {
    promise,
    abort: () => {
      _rej({
        name: "abort",
        message: "the promise is aborted",
        aborted: true,
      });
    }
  };
}
//主逻辑提取出来
function runCb(resolve,reject){
    setTimeout(()=>{
        resolve('1111')
    },3000)
}
const { promise, abort } = getPromise(runCb);
promise.then(console.log).catch(e => {
  console.log(e);
});

方案2  - 借助 Promise.race() 方法

相信大家都知道race方法的作用,这里还是简单介绍下。

当有若干个promise, p1, p2, p3…在调用, let p = Promise.race([p1, p2, p3,…])的时候,返回的p也是一个promise。那么p什么时候会被resolve或者被reject呢?

看race我们知道它是竞速或赛跑的意思,所以p1, p2, p3 … 最先一个被resolve或者被reject的结果就是p的resolve或者reject的结果。所以后续的promise的resolve和reject都不会再被执行了。

代码很简单,其实够短小精悍。

//传入一个正在执行的promise
function getPromiseWithAbort(p){
    let obj = {};
    //内部定一个新的promise,用来终止执行
    let p1 = new Promise(function(resolve, reject){
        obj.abort = reject;
    });
    obj.promise = Promise.race([p, p1]);
    return obj;
}

调用

var promise  = new Promise((resolve)=>{
 setTimeout(()=>{
  resolve('123')
 },3000)
})
var obj = getPromiseWithAbort(promise)
obj.promise.then(res=>{console.log(res)})
//如果要取消
obj.abort('取消执行')

85be1ea3086eb55cfd13ac1dc53cf3f7_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png

借助race方法明显的更简洁,更易用。

最后


其实取消promise执行和取消请求是一样的,并不是真的终止了代码的执行,而是对结果不再处理。另外fetch api虽然增加了新的标准实现,但仍然存在兼容问题,而且只能在浏览器中使用。那么非浏览器的环境中呢?比如RN?所以如果想要达到一种通用的方式,那么本文的取消promise的方式应该是个不错的方式。

目前知名的axios库也有abort能力,回头看下它的实现方式,也欢迎小伙伴们留言讨论。

---end,希望对你有用。

目录
相关文章
|
1月前
|
前端开发 JavaScript
js开发:请解释Promise是什么,以及它如何解决回调地狱(callback hell)问题。
Promise是JavaScript解决异步操作回调地狱的工具,代表未来可能完成的值。传统的回调函数嵌套导致代码难以维护,而Promise通过链式调用`.then()`和`.catch()`使异步流程清晰扁平。每个异步操作封装为Promise,成功时`.then()`传递结果,出错时`.catch()`捕获异常。ES6的`async/await`进一步简化Promise的使用,使异步代码更接近同步风格。
40 1
|
8月前
|
前端开发
13 # promise 的状态更改问题
13 # promise 的状态更改问题
43 0
|
前端开发
前端学习案例16-promise的理解方式&调用机制3
前端学习案例16-promise的理解方式&调用机制3
59 0
前端学习案例16-promise的理解方式&调用机制3
|
前端开发
前端学习案例15-promise的理解方式&调用机制2
前端学习案例15-promise的理解方式&调用机制2
58 0
前端学习案例15-promise的理解方式&调用机制2
|
前端开发
前端学习案例3-promise的理解方式和调用机制2
前端学习案例3-promise的理解方式和调用机制2
49 0
前端学习案例3-promise的理解方式和调用机制2
|
前端开发
前端学习案例17-promise的理解方式&调用机制4
前端学习案例17-promise的理解方式&调用机制4
52 0
前端学习案例17-promise的理解方式&调用机制4
|
前端开发
前端学习案例14-promise的理解方式&调用机制1
前端学习案例14-promise的理解方式&调用机制1
58 0
前端学习案例14-promise的理解方式&调用机制1
|
前端开发
前端学习案例2-promise的理解方式和调用机制1
前端学习案例2-promise的理解方式和调用机制1
43 0
前端学习案例2-promise的理解方式和调用机制1
|
前端开发
前端学习案例9-promise和回调地狱1
前端学习案例9-promise和回调地狱1
49 0
前端学习案例9-promise和回调地狱1
|
前端开发
前端学习案例10-promise和回调地狱2
前端学习案例10-promise和回调地狱2
44 0
前端学习案例10-promise和回调地狱2