await Promise内部执行setTimeout定时器,提前clearTimeout,导致卡死的情况分析及解决方案

news2024/11/16 9:16:32

背景概述

在我们日常开发中,我们常常需要在某个地方暂停某个动作一段时间。这个时候,我们的通常做法是使用setTimeout,配合promise实现。也就是如下代码。

function delay(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Delayed value');
    }, ms);
  });
}

async function example() {
  console.log('Before delay');

  await delay(2000); // 等待Promise的resolve操作完成

  console.log('After delay');
}

但我们偶尔需要提前终止这个定时器。这时候我们会需要使用JavaScript 自带的clearTimeout方法,这个方法要求我们传入 timeoutId,也就是这个定时器的Id

const timeoutId = setTimeout(() => {

}, ms)
clearTimeout(timeoutId)

遭遇问题

如上所述,我们在某个地方暂停某个动作一段时间。这个时候,我们的通常做法是使用setTimeout,配合promise实现。又需要提前终止这个定时器。我们普遍的做法是让一个外部变量接受这个setTimeout的返回值。然后在需要终止他的地方,调用clearTimeout,终止这个定时器。

let timeoutId = '';
function delay(ms) {

  const promise = new Promise((resolve, reject) => {
    timeoutId = setTimeout(() => {
      resolve("Delayed value");
    }, ms);
  });

  return promise;
}

或者是内部定义方法

function delay(ms) {
  let timeoutId; // 保存timeoutId的变量

  const promise = new Promise((resolve, reject) => {
    timeoutId = setTimeout(() => {
      resolve("Delayed value");
    }, ms);
  });

  // 添加一个stop方法,用于提前停止延迟操作
  promise.stop = () => {
    clearTimeout(timeoutId);
  };

  return promise;
}

但是这两种都有同样的一个问题

async function example() {
  console.log("Before delay");

  const promise = delay(2000); // 获取延迟操作的Promise对象

  setTimeout(() => {
    promise.stop(); // 提前停止延迟操作
    console.log("Stopped delay");
  }, 1000);

  await promise; // 等待Promise的resolve操作完成

  console.log("After delay");
}

example();

在这里插入图片描述

后续代码的 console.log(“After delay”)就至此不会再被执行了。

原因分析

await紧跟一个没有resolve/reject的promise对象,则后续的代码不会被执行。举个小例子

async function a(){
    // 如果await后是promise对象 
    await new Promise(resolve => {
        console.log(66666)
    })
    console.log(1) // 这一行并不会被执行到
}
a();

也就是说这里的 await 所等待的 promise的状态永远是处于 pending 状态的。

我们上述的代码中的resolve()在setTimeout内部,当定时器被提前终止的时候,定时器内部的回调函数不会被调用,也就是resolve从此不会被任何东西调用。导致 promise永远处于pending状态,而await 永远等待这个pending状态的代码执行。则await后续代码永远不会被执行。

解决方法

我们可以使用AbortControllersetTimeout结合的方式来中断延迟操作,并在需要中断的时候调用abort方法。这样,中断操作后的代码就会执行,从而实现提前停止延迟操作。

在这里插入图片描述

AbortController通常用来终止web请求,和我们这个有异曲同工之妙。

解决代码如下

function delay() {
  const controller = new AbortController();
  const signal = controller.signal;

  const promise: any = new Promise((resolve, reject) => {
    const timeoutId = setTimeout(() => {
      resolve("Delayed value");
    }, 60000);

    signal.addEventListener("abort", () => {
      clearTimeout(timeoutId);
      resolve("Delayed value");
    });
  });

  promise.stop = () => {
    controller.abort();
  };

  return promise;
}

async function example() {
  console.log('Before delay');

  const promise = delay(2000);

  setTimeout(() => {
    promise.stop();
    console.log('Stopped delay');
  }, 1000);

  await promise;
  console.log('After delay');
}

example();

这样就能正常调用啦
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/935392.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

redis数据库及其常用数据结构

redis数据库 非关系型数据库 非关系型数据库是什么? 非关系型数据库其实是相对于关系型数据库而言的,关系型数据库中同种数据存储在一张表中,使用表将不同种类的数据进行分隔并且表中的数据如果存在主键,也可以根据主键确定表与…

tableau基础学习1:数据源与绘图

文章目录 读取数据常用绘图方法1. 柱状图2. 饼图3. 散点图4. 热力图 第一部分是一些较容易上手的内容,以及比较常见的可视化内容,包括:柱状图、饼图、散点图与热力图 读取数据 打开界面后,选择数据源之后就可以导入数据&#xf…

【操作记录】CLion 中引入 Gurobi 并使用 C++ 编程

文章目录 一、前言二、具体操作2.1 创建项目2.2 修改编译工具2.3 修改 CMakeLists.txt2.4 修改 main.cpp2.5 运行测试 一、前言 虽然C编程大部分人都会选择使用VS,但是作为 IDEA 的长期用户,我还是比较习惯 JetBrains 风格的编译器,所以就选…

Go测试之.golden 文件

Go测试中的.golden 文件是干什么用的?请举例说明 在Go语言中,.golden文件通常用于测试中的黄金文件(golden files)。黄金文件是在测试期间记录预期输出结果的文件。测试用例运行时,黄金文件用于比较实际输出与预期输出…

Autosar存储入门系列03_NVM状态机及读写存储调用逻辑

本文框架 0.前言1. NVM状态机介绍2. NVM读/写基本逻辑2.1 NVM读操作2.2 NVM写操作2.2.1 实时写2.2.2 下电写 2.3 NVM写入注意事项 0.前言 本系列是Autosar存储入门系列,希望能从学习者的角度把存储相关的知识点梳理一遍,这个过程中如果大家觉得有讲得不…

Go 第三方库引起的线上问题、如何在线线上环境进行调试定位问题以及golang开发中各种问题精华整理总结

Go 第三方库引起的线上问题、如何在线线上环境进行调试定位问题以及golang开发中各种问题精华整理总结。 01 前言 在使用 Go 语言进行 Web 开发时,我们往往会选择一些优秀的库来简化 HTTP 请求的处理。其中,go-resty 是一个被广泛使用的 HTTP 客户端。…

还在为Compose组件管理苦恼?Jetpack Compose的版本控制清单(BOM)扫除你的苦恼

还在为Compose组件管理苦恼?Jetpack Compose的版本控制清单(BOM)扫除你的苦恼 Jetpack Compose通过简化和提高效率,彻底改革了Android UI开发。其中一个有助于此的功能是Jetpack Compose版本控制清单(BOM)…

vue2 组件组成部分,组件通信,进阶语法

一、学习目标 1.组件的三大组成部分(结构/样式/逻辑) ​ scoped解决样式冲突/data是一个函数 2.组件通信 组件通信语法父传子子传父非父子通信(扩展) 4.进阶语法 v-model原理v-model应用于组件sync修饰符ref和$refs$nextTic…

3、当今的企业架构分析

3、当今的企业架构分析 3、分库分表水平拆分(MySQL集群) 因为一个数据库装不下了,需要分库分表,读写分离,主从复制,主节点M与从节点s组成了一个数据库的集群,组成了一个小的单元,前端…

Axure RP软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 Axure RP是Axure公司开发的一款原型设计工具,广泛应用于产品设计和UI/UX设计领域。以下是Axure RP软件的主要特点和功能: 原型设计:Axure RP提供了丰富的界面元素和交互元素,用户…

django的简易的图书管理系统jsp书店进销存源代码MySQL

本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 django的简易的图书管理系统 系统有1权限&#xff1a…

使用WebDriver采样器将JMeter与Selenium集成

第一步: 在JMeter中添加Selenium / WebDriver插件 第二步: 创建一条测试计划–添加线程组 添加配置元素 - jpgc - WebDriver Sampler 添加配置元素 - jpgc - Chrome Driver Config 并且添加监听器查看结果树 第三步: 下载 chromedriver…

时序预测 | MATLAB实现Attention-GRU时间序列预测(注意力机制融合门控循环单元,TPA-GRU)

时序预测 | MATLAB实现Attention-GRU时间序列预测----注意力机制融合门控循环单元,即TPA-GRU,时间注意力机制结合门控循环单元 目录 时序预测 | MATLAB实现Attention-GRU时间序列预测----注意力机制融合门控循环单元,即TPA-GRU,时…

煤矿皮带运输智能监控算法 opencv

煤矿皮带运输智能监控算法通过opencvpython深度学习算法网络模型,煤矿皮带运输智能监控算法实时监测皮带运输过程中的各种异常情况,如跑偏、撕裂、堆料异常等,一旦检测到异常情况,立即发出告警并采取相应的措施,以保障…

搭建开发环境-WSL+Ubuntu(一键搭建开发环境)

概述 所谓工欲善其事必先利其器,搭环境往往是开发过程中卡出很多初学者的拦路虎。 对于很多老鸟来说,很多东西都已经习惯成自然,也就没有刻意和初学者说。但对于很多初学者,却是受益良多。 这个系列,先从操作系统开始…

MySQL数据库——约束(概述、约束演示、外键约束、删除/更新行为)

目录 概述 约束演示 表格创建 验证 图形化界面约束 外键约束 概念 语法 外键删除/更新行为 总结 概述 概念:约束是作用于表中字段上的规则,用于限制存储在表中数据。目的:保证数据库中数据的正确、有效性和完整性。分类&#xff1…

有哪些常人不知道的赚钱方法?

在目前互联网时期,如果说还有什么挣钱方法让别人不知道,那一定是赚大钱或者违法乱纪的挣钱渠道。但是对于普通人而言,确实是有一些挣钱的方法不被其了解,我这里就介绍几个,供大家一起探讨。 第一个:知识变…

TCP/IP五层模型、封装和分用

1.网络通信基础2.协议分层OSI七层协议模型TCP/IP五层/四层协议模型【重点】 3. 封装&分用 1.网络通信基础 IP地址:表示计算机的位置,分源IP和目标IP;举个例子:买快递,商家从上海发货,上海就是源IP&…

爱奇艺数据湖实战 - 基于数据湖的日志平台架构演进

01 背景 为了满足公司内日志实时查询分析的需求,爱奇艺大数据团队自研了Venus日志服务平台,负责爱奇艺各服务日志的采集、存储、处理、分析等场景。早期采用基于ElasticSearch的存储分析架构,随着数据规模的不断扩大,出现了成本高…

C语言基础之——指针(上)

前言:小伙伴们又见面啦!本期内容,博主将展开讲解有关C语言中指针的上半部分基础知识,一起学习起来叭!!! 目录 一.什么是指针 二.指针类型 1.指针的解引用 2.指针-整数 三.野指针 1.野指针…