我的编程空间,编程开发者的网络收藏夹
学习永远不晚

取消正在运行的Promise技巧详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

取消正在运行的Promise技巧详解

前言

最近项目当中小伙伴遇到一个很奇怪的bug,进入一个页面后,快速切换到其它页面,会跳转到403页面。经过一段时间和小伙伴的排查,发现那个页面有个接口请求响应时间比较长,请求后还有一些业务处理。

等我们切换到其它页面,这个请求完成后还会处理剩下的业务,导致出错。

代码案例

项目当中有很多业务,我们用一些简单代码复现下这个问题。

import React, { useEffect } from 'react';
import { history } from 'umi';
const Test = props => {
  useEffect(() => {
    new Promise((resolve, reject) => {
        // 模拟接口请求时间
        setTimeout(() => {
            resolve()
        }, 4000);
    }).then(res => {
        return new Promise((resolve1) => {
             // 模拟接口请求时间
            setTimeout(() => {
                resolve1()
            }, 1000);
        })
    }).then(() => {
        // Promise 执行完后页面跳转
        history.push('/test1')
    })
  }, []);
  const go = () => {
    history.push('/user/login')
  }
  return (
    <div>
      <button onClick={go}>go to</button>
      Test
    </div>
  );
}
export default Test;

我们进入Test组件后,马上点击go to按钮,几秒之后页面还会跳转到test1页面。

经分析,我们应该在离开的时候要取消请求和取消Promise让后续的业务代码不在执行,取消请求比较简单,一般的库都支持,我们来说下怎么取消Promise.

CancelablePromise (取消Promise)

我们知道Promise是没有提供取消或者终止的操作。但我们在开发过程中会遇到。我们可以参考和借助AbortController来实现。

class CancelablePromise<T> {
  
  constructor(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void, abortSignal: AbortSignal) {
    // 记录reject和resolve方法
    let _reject: any = null;
    let _resolve: any = null;
    let _isExecResolve = false;
    // 创建和执行Promise
    const cancelablePromise = new Promise<T>((resolve, reject) => {
      _reject = reject;
      _resolve = (value: T) => {
        _isExecResolve = true;
        resolve(value);
      };
      return executor(_resolve, reject);
    });
    // 监听Signal的abourt事件
    abortSignal.addEventListener('abort', () => {
      if (_isExecResolve) {
        return;
      }
      // 抛出错误
      const error = new DOMException('user cancel promise', CancelablePromise.CancelExceptionName );
      _reject( error );
    } );
    return cancelablePromise;
  }
  // 取消后抛出的异常名称
  static CancelExceptionName = 'CancelablePromise AbortError';
}
export default CancelablePromise;

使用

下面我们该造下之前的代码,用我们封装的CancelablePromise,可以让Promise可取消。

多个Promise链式调用

import React, { useEffect } from 'react';
import { history } from 'umi';
import CancelablePromise from '../utils/CancelablePromise';
const Test = props => {
  useEffect(() => {
   let abortController = new AbortController();
    new CancelablePromise((resolve, reject) => {
        // 模拟接口请求时间
        setTimeout(() => {
            resolve()
        }, 4000);
    }, abortController.signal).then(res => {
        return new CancelablePromise((resolve1) => {
             // 模拟接口请求时间
            setTimeout(() => {
                resolve1()
            }, 1000);
        }, abortController.signal)
    }).then(() => {
        // Promise 执行完后页面跳转
        history.push('/test1')
    })
    return () => {
        // 取消请求
        abortController.abort();
    }
  }, []);
  const go = () => {
    history.push('/user/login')
  }
  return (
    <div>
      <button onClick={go}>go to</button>
      Test
    </div>
  );
}
export default Test;

在async和await中使用

import React, { useEffect } from 'react';
import { history } from 'umi';
import CancelablePromise from '../utils/CancelablePromise';
const Test = props => {
  useEffect(() => {
      let abortController = new AbortController();
     const exec = async function () {
      try {
        await new CancelablePromise((resolve) => {
          setTimeout(() => {resolve();}, 5000);
        }, abortController.signal, 'one')
        await new CancelablePromise((resolve1) => {
          setTimeout(() => {resolve1();}, 5000);
        }, abortController.signal, 'del')
        history.push('/test')
      } catch (error) {
        // 取消之后会抛出异常
        if (CancelablePromise.CancelExceptionName === error.name) {
          console.log('promise 终止了。。。')
        }
      }
    }
    exec();
    return () => {
        // 取消请求
        abortController.abort();
    }
  }, []);
}

Promise取消之后会抛出异常,如果需要在抛出异常之后做处理,可以通关对应的异常名称做判断。

if (CancelablePromise.CancelExceptionName === error.name) {
  console.log('promise 终止了。。。')
}

结束语

Promise的取消在业务当中用到的地方比较多,更多关于Promise运行取消的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

取消正在运行的Promise技巧详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何取消正在运行的Promise

本篇内容介绍了“如何取消正在运行的Promise”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!代码案例项目当中有很多业务,我们用一些简单代码
2023-07-02

Win8系统程序运行不正常提示联机检查解决方案的取消技巧

我们在使用Windows 8系统的时候,偶尔会遇到某些程序不能正常运行,系统提示需要联机检查解决方案。很多用户对这个提示感到厌烦,下面教大家如何通过修改注册表来取消这个提示。操作步骤1.按“Win+R”组合键打开运行
2022-06-04

MySQL如何查看正在运行的SQL详解

目录前言processlistthreadsevents_statements_current如何查看正在运行的SQL拿到正在执行的processlist_id拿到与processlist_id对应的thread_id拿到正在执行的sql语
2023-01-12

Python 异步之如何获取当前和正在运行任务详解

这篇文章主要为大家介绍了Python 异步之如何获取当前和正在运行任务详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-03-22

Java -jar参数详解:掌握Java可执行JAR文件的运行技巧

作为一种常用的开发语言,Java经常使用可执行的JAR(Java Archive)文件来打包和分发应用程序。使用java -jar命令运行JAR文件是一种方便快捷的方式。本文将详细介绍java -jar命令的各种参数,帮助您充分利用这个功能
2023-08-17

编程热搜

目录