js轮询及踩过的坑

「JavaScript深入」轮询(Polling):基础的实时通信方式 轮询技术作为实时通讯的基础方案,虽然在新一代技术面前略显陈旧,但在特定场景下仍具有实用价值。开发者应充分理解各种技术的优缺点,根据实际需求选择最合适的解决方案。随着HTTP/3和WebTransport等新技术的发展,实时通讯领域将迎来更多创新和突破。 阅读详情

背景

  • 下午四点,天气晴朗,阳光明媚,等着下班
  • 产品:我希望页面上的这个数据实时变化
  • 开发:···,可以,用那个叫着WebSocket的东西,再找一个封装好框架,如:mqtt(感觉自己好机智)
  • 产品:要开发好久
  • 开发:嗯,三天,五天,还是···
  • 产品:我希望今天上线
  • 开发:···,···,···(不能描述的语言,话说segmentfault为什么不支持表情)
  • 开发:果断选择轮询

开发中

<!DOCTYPE HTML>
<html>
<head>
  <title>轮询的坑</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
</body>
<script type="text/javascript">
  function getData() {
      return new Promise((resolve,reject) => {
          setTimeout(() => {
              resolve({data:666})
          },500)
      })
  }
  // 轮询
  async function start () {
    const { data } = await getData() // 模拟请求
    console.log(data)
    timerId = setTimeout(start, 1000)
  }
  start ()
</script>
</html>

开发:今晚的月亮真圆啊,下班了···

第二天

  • 产品:我希望这个实时加载,能随心所欲,我喊它加载就加载,喊它停就停
  • 研发:(石化中···)
  • 继续开发中
<!DOCTYPE HTML>
<html>
<head>
  <title>轮询的坑</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
    <button id="button">暂停</button>
</body>
<script type="text/javascript">
  let timerId = null
  function getData() {
      return new Promise((resolve,reject) => {
          setTimeout(() => {
              resolve({data:666})
          },500)
      })
  }
  // 轮询
  async function start () {
    const { data } = await getData() // 模拟请求
    console.log(data)
    timerId = setTimeout(start, 1000)
  }
  // 暂停
  function stop () {
    clearTimeout(timerId)
  }

  start ()

  const botton = document.querySelector("#button")
  let isPlay = true
  botton.addEventListener("click", function(){
    isPlay = !isPlay
    botton.innerHTML = isPlay ? '暂停' : '播放'
    isPlay ? start() : stop()
  }, false)
</script>
</html>
  • 开发:(这么难得需求我都实现了,我是不是已经是专家了,我是不是应该升职加薪,接着赢娶白富美,走向人生巅峰,哈哈哈)
  • 正沉醉于自己的成果中
  • 产品:你的有bug
  • 开发:(绝对不信中,肯定是你握鼠标的姿势不对,手感不好),怎么可能有bug,你是不是环境有问题,还在用ie6,多刷新几次
  • 产品:···,你按钮多点几次,点快点,试试,数据会多次请求
  • 开发:半信半疑的去尝试,还真是(好奇怪,检查了一圈没有发现任何问题)

分析过程

  1. 一进去页面执行start(),start是一个async函数,使得里面的异步也会像同步一样执行,函数的末尾timerId = setTimeout(start, 1000),1000毫秒后再次执行start(),形成了一个轮询(这里的每一个请求之间的间隔肯定是大于1000+500的,至于为什么,可以去了解一下浏览器异步执行原理)
  2. 将setTimeout的id赋值给timerId,点击按钮后,清除当前定时器

看似没有任何问题,找不到问题的时候就只有一点点试错,最终发现去掉const { data } = await getData()之后,问题消失,请求的时间越长,出现的概率越高
画个图分析一下
在这里插入图片描述
先看一下js执行过程,按钮的click事件也相当于异步,然后我们再来文字分析一下,问题出现的原因

bug出现原因

  1. 假如没有const { data } = await getData()这步,点击的时候,click的回调函数能够执行,说明当前js肯定处于空闲状态(永远记住,js的单线程的),这时的setTimeout(start, 1000)一定处于异步状态(js一次只有执行一个任务),
  2. clearTimeout(timerId)可以很轻松的清除这次任务,不会让它进入js执行线程中执行
  3. 加上const { data } = await getData()之后,如果js现在处于setTimeout的回调函数已经执行并且等待await getData()中,js是空闲的,click可以执行,click清除了setTimeout的回调函数的执行(回调函数已经执行了),没有清除await getData()回调函数的执行,代码会继续执行console.log(data);timerId = setTimeout(start, 1000),从而不能停止循环,这就是bug产生的原因
    在这里插入图片描述
    这就是为什么,请求的时间越长,出现的概率越高

解决方案

<!DOCTYPE HTML>
<html>
<head>
  <title>轮询的坑</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
    <button id="button">暂停</button>
</body>
<script type="text/javascript">
  let timerId = 1 // 模拟计时器id,唯一性
  let timerObj = {} // 计时器存储器
  function getData() {
      return new Promise((resolve,reject) => {
          setTimeout(() => {
              resolve({data:666})
          },500)
      })
  }
  // 轮询
  function start () {
    const id = timerId++
    timerObj[id] = true
    async function timerFn () {
      if (!timerObj[id]) return
      const { data } = await getData() // 模拟请求
      console.log(data)
      setTimeout(timerFn, 1000)
    }
    timerFn()
  }
  // 暂停
  function stop () {
    timerObj = {}
  }

  start ()

  const botton = document.querySelector("#button")
  let isPlay = true
  botton.addEventListener("click", function(){
    isPlay = !isPlay
    botton.innerHTML = isPlay ? '暂停' : '播放'
    isPlay ? start() : stop()
  }, false)
</script>
</html>

转载自:https://segmentfault.com/a/1190000014460305

JavaScript —— JavaScript 轮询机制和异步任务处理工具函数详解 阅读详情

相关推荐

极空间NAS零基础部署Wiki.js:Docker+PostgreSQL全流程避坑指南

本文提供了一份在极空间NAS上从零部署Wiki.js私有知识库的详细指南。通过Docker容器化技术,结合PostgreSQL数据库,手把手讲解环境准备、核心组件配置、性能优化及安全加固等全流程,并特别针对极空间平台特性提供了避坑要点,帮助用户打造安全、高效、自主可控的知识管理系统。

3a9bq4r8t2y的博客 486

JavaScript性能优化-内存问题篇

前言 在应用程序运行过程中,如果内存出现了问题,具体有怎样的体现 内存问题的外在表现 1.页面出现延迟加载或经常性暂停(限定网络情况正常) 2.页面持续性出现糟糕的性能(限定网络情况正常) 3.页面的性能随时间延长越来越差(限定网络情况正常) 界定内存问题的标准 1.内存泄漏:内存使用持续走高 2.内存膨胀:在多数设备上都存在性能问题 3.频繁垃圾回收:通过内存变化图进行分析 监控内存的几种方式 1.浏览器任务管理器 2.Timeline时序图记录 3.堆快照查找分离DOM 4.判断是.

往事不回头,余生不将就 487

编译原理实验二:LL(1)分析法(附C/C++完整代码)

本文讲述了LL(1)文法的原理及如何用C语言实现。并在给出的代码中实现了消除文法的左递归,First集,Follow集,select集的输出,构造预测分析表并输出,和对任意输入字符串的分析。程序总流程为:从文件读取文法 -> 输出文法信息 -> 消除左递归并输出消除后的文法 -> 计算First集并输出 -> 计算Follow集并输出 ->计算select集并输出 -> 判断是否是LL(1)文法 -> 构造预测分析表并输出 ->手动输入要分析的字符串 -> 输出分析过程和结果读取文件。

W_Wmwmwm的博客 6192

js定时器一直开启会增加内存么_JavaScript各种定时器总结

setTimeout与setIntervalsetTimeout和setInterval已经存在已久了,我们什么场景下会使用它们完成我们的业务呢?我列举一些例子:轮询接口动画不知名的bug去解决我们会遇到使用它们的场景其实归纳起来就是以上三点。轮询接口这种情景,一般出现在不用socket的情况下使用的,例如我们有一个支付功能,前端调用了sdk获取h5支付链接后,页面就需要轮询一个后端的接口去查询这...

weixin_39859819的博客 1546

英飞凌AURIX™ TC3xx系列MCU的ISO 26262安全机制实战:从安全手册到代码集成的避坑指南

本文深入探讨英飞凌AURIX™ TC3xx系列MCU的ISO 26262安全机制实战应用,重点解析锁步核配置、ECC策略优化及SafeTlib库集成中的关键问题。通过代码示例和配置建议,帮助开发者实现ASIL D级别安全性,规避常见陷阱,提升汽车电子系统的功能安全合规性。

weixin_42558093的博客 405

PLDM实战解析:传感器与效应器在智能监控系统中的应用

本文深入解析了PLDM(平台级数据模型)中传感器与效应器两大核心组件在智能监控系统中的应用。传感器负责感知硬件状态,分为数值型与状态型,提供精准的“体检报告”;效应器则负责执行控制指令,实现从监控到操作的闭环。文章通过实战案例,阐述了如何利用这些标准化组件构建高效、自动化的智能监控系统,并探讨了平台描述记录与事件机制等关键技术。

k6l7m8n9的博客 874

Js的长轮询

长轮询是与服务器保持持久连接的最简单的方式,它不使用任何特定的协议,例如 WebSocket 或者 Server Sent Event。 它很容易实现,在很多场景下也很好用。

Front end development engineer 4万+

MuJoCo与Isaac Sim的无缝对接:利用USD导出功能实现强化学习场景的跨平台迁移

本文详细介绍了如何通过USD导出功能实现MuJoCo与Isaac Sim的无缝对接,助力强化学习场景的跨平台迁移。文章解析了USD格式的核心优势,包括分层合成、物理属性继承和时间轴动画,并提供了从MJCF到USD的完整转换流程及在Isaac Sim中的高级应用技巧,帮助开发者高效迁移和优化强化学习环境。

weixin_29073241的博客 517

js 轮询 html5,js轮询及踩过的坑

背景下午四点,天气晴朗,阳光明媚,等着下班产品:我希望页面上的这个数据实时变化开发:···,可以,用那个叫着WebSocket的东西,再找一个封装好框架,如:mqtt(感觉自己好机智)产品:要开发好久开发:嗯,三天,五天,还是···产品:我希望今天上线开发:···,···,···(不能描述的语言,话说segmentfault为什么不支持表情)开发:果断选择轮询开发中轮询的坑function get...

weixin_42099987的博客 419

2025年下半年网络规划设计师综合知识真题及答案解析

1983年,ARPANet完成技术转型,对此后的 Internet发展全关重要,这一转型是指( ) A.电路交换转向分组交换 B.商业化转型 C.民用化转型 D.从 NCP 协议转向 TCP/IP 答案:D 解析:ARPANet 最初使用 NCP (Network Control Protocol)协议进行主机问通信。1983年1月1日,ARPANet 正式切换到TCP/IP 协议族,为后续Internet的发展奠定了统一协议基础。

鹿鸣天涯 928

FreeRTOS深入教程(任务创建的深入和任务调度机制分析)

本篇文章将带大家深入学习任务的创建和分析任务调度的机制。本篇文章深入的讲解了任务创建的内部实现和任务调度的源代码分析和实现,学习这篇文章有助于更深入的学习FreeRTOS的源码。

m0_49476241的博客 6391

js轮询之setInterval踩坑小记

写在开头 最近负责的项目要接入计费功能,有了计费自然需要充值。说起充值,无外乎支付宝、微信和网银了,然后前端调用充值接口后,需要起一个轮询任务,去监听支付状态,根据轮询结果来进行下一步的操作(当然了,有条件的大户人家想要直接上websocket也没问题)。所以,业务场景倒是很easy,梳理完逻辑我就吭哧吭哧开搞了… 发现问题 然而,当我基本写完在调试时,发现每次轮询停止了,页面上的状态会刷新两次。当时的业务是需要我在支付状态时显示验证码过期的倒计时,然而倒计时结束后会重新计时一次,这里可以不关心,原因就是轮

逸尘的专栏 2992

【原理图与PCB专题】使用Cadence如何在Layout时直接互换相同功能的PIN

Cadence允许我们在PCB中互换管脚,最后再反标给原理图。集成TVS管、排阻、DDR、FPGA有一些PIN是完全相同功能,可进行管脚互换的,建议使用这个功能。可降低硬件工程师与Layout工程师之间沟通成本,加快设计进度。

一点硬件 801

javascript 轮询_JavaScript轮询

JavaScript轮询 使用JavaScript进行轮询是高级前端用户体验和测试实践中那些难看但重要的功能之一。 有时没有事件可以挂起,以表示给定任务已完成,因此您需要动手进行简单的轮询。 用JavaScript轮询并不困难,但也不容易。 让我向您展示一些可以添加到工具箱中JavaScript轮询的实现! 有诺言 由于Promise API目前已实现几乎所有浏览器,因此以下是使用...

Web 开发&软件开发 1270

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

JS事件轮询机制(Event Loop)

概念     事件轮询 (eventloop) 是"一个解决和处理外部事件时将它们转换为回调函数的调用的实体(entity)"     JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。所有任务都需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。 任务队列     “ 任务队列 " 是一个先进先出的数据结构,排在前面...

关注最新技术问题并持续维护更新 9965

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

JS事件轮询

此篇文章记录了油管上的一次关于事件循环的演讲,其中剖析了事件环、轮循机制、RAF与微任务,以一篇教程的形式来书写,其中也包含了作者对于事件循环的一点见解。

Col0ring的博客 1969

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket

IM通信技术是现代应用中至关重要的一部分,开发者可以根据实际需求选择不同的通信技术。本文介绍了短轮询、长轮询、Server-Sent Events(SSE)、WebSocket 这四种通信技术的原理和实现方式,并通过简单的代码示例演示了它们的应用。在选择合适的通信技术时,需要根据实际场景的需求、安全性、性能等因素进行综合考虑。随着技术的不断发展,IM通信技术也会迎来更多的创新和改进,为开发者提供更多选择。😊🙏Java面试技巧Java面试八股文 - 掌握面试必备知识(目录篇)Java学习路线。

学IT,找陈寒 6184

js轮询

这里先要介绍三个方法 setInterval setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。 例如: setInterval(function(){ alert("Hello world"); }, 3000); setInterval('alert("Hello world");', 3000); clearInterval clearInterval() 方法可取消由 setInterval() 函数设定的定时执行操作。 clearInterval() 方法

wang982521971的博客 1425

js事件轮询(event loop)

以代码执行顺序而言,先代码同步执行,先同步后异步,异步中执行一个宏任务之后清空微任务,然后再执行一个宏任务,然后再清空微任务。!!new promise是同步任务,promise.then才是微任务。练习部分,可以先自己做一下,然后不懂之处借鉴之后的讲解部分。讲解二略冗长是为了更为清晰的介绍事件轮询机制,核心是这个机制,练习是帮助理解。不对之处,欢迎指正,模糊之处,欢迎讨论。

zkx529的博客 1581

js调用轮询接口

项目中遇到需要很多个需要轮询处理的接口,然后简单的封装了下,做个记录,以后用到类似的直接copy // polling-utils.js /** * @descripting 轮询功能 * @param {String} type 请求类型 * @param {String} url 地址 * @param {Object} data 请求数据...

weixin_30425949的博客 3391

JavaScript轮询:实现异步更新的古老技术

本文将介绍JavaScript轮询的基本概念和用法,以及它在实际开发中的应用。JavaScript轮询是一种古老的异步更新技术,通过定时向服务器发送请求来检查数据的变化。了解轮询的原理和用法对于开发者来说具有重要意义。掌握轮询的使用可以帮助我们更高效地实现实时数据更新和同步。

你若盛开,清风自来 1361

js的事件轮询机制

js的事件轮询机制

czx3387170的博客 822

JS轮询及其BUG

普通轮询 <!DOCTYPE HTML> <html> <head> <title>轮询的坑</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> </head> <body> </body> <script type="text/javascript"> function ge

DJDU博客 645
上一篇: PHP 获取客户端 IP 地址
下一篇: CentOS7 yum 安装 PHP7.2
dadeity
博客等级 码龄10年 1172粉丝 225原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值