热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaScript实现可终止轮询请求的方法【java基础】【Js面试】

轮询请求就是间隔相同的时间(如5s)后不断地向服务端发起同一个接口的请求,当然不能无限次去请求,所以轮询必须要有个停止轮询的机制,今天通过本文给大家介绍JavaScript实现可终

最近遇到了一个需求,需要每隔5s请求一个接口获取接口返回的结果,返回成功后停止请求,接口的返回的值有下面几种情况:

// 成功
{
    "code": 0,
    "msg": "成功"
}
// 查询中
{
    "code": -1,
    "msg": "结果查询中"
}
// 失败
{
    "code": 1,
    "msg": "返回结果失败"
}

code是接口的状态码,为0的时候表示接口返回的成功,这时就不需要再请求接口。

实现这种需求首先想到的就是用轮询去做了。

什么是轮询请求?

通俗地说,轮询请求就是间隔相同的时间(如5s)后不断地向服务端发起同一个接口的请求,当然不能无限次去请求,所以轮询必须要有个停止轮询的机制

轮询的要点

1. 按照需要选择是否立即发起请求再进入轮询

2. 上一次的请求响应后到了指定的时间间隔后再继续执行下一次请求

3. 当轮询的请求发生报错的时候应该停止轮询

4. 被停止的轮询可以根据需要再次发起轮询

setInterval的问题

因为是不断请求,所以首先能想到的就是用setInterval去实现,但是setInterval做轮询的话,会有以下严重的问题

1. 即使调用的代码报错了,setInterval会持续的调用

2. setInterval不会等到上一次的请求响应后再执行,只要到了指定的时间间隔就会执行,哪怕有报错也会执行

3. setInterval定时不准确,这个跟事件循环有关,这里不展开啦~

实现轮询

实现轮询,只要按照轮询的要点去实现一个setInterval方法就可以了,下面用setTimeout一步步去实现这个方法

准备工作

首先准备一个html模板,这个模板包含两个按钮,一个开启轮询,一个停止轮询,轮询的方法命名为myInterval,返回一个startstop方法用于开始和停止轮询


  
    
    
    
    
  
  
    
    
  

基础版

function myInterval(callback, interval = 2000) {
    let timerId
    const loop = async () => {
      callback()
      return (timer = setTimeout(loop, interval))
    }
    return {
      start: () => {
        loop()
      },
      stop: () => {
        console.log("停止执行")
        clearTimeout(timerId)
      }
    }
  }

这个版本基本跟setInterval的功能一致了,只不过执行需要手动调用start,停止要调用stop。

一个常见的场景是,当轮询执行n次后,停止轮询,下面改一下main方法,等count等于5的时候停止轮询

function main() {
    count += 1
    console.log("执行:", count)
    if (count == 5) {
      count = 0
      intervalManager.stop()
    }
}

发现当count等于5时,确实调用了stop方法,但是却没有停止轮询,当点击停止按钮的时候,又停止了轮询,这是什么情况呢?

看一下loop方法

const loop = async () => {
  callback()
  return (timerId = setTimeout(() => {
    loop()
  }, interval))
}

因为是在callback中执行stop的,stop并没有阻止定时器中回调(loop)的执行,所以看起来是停止了,但是新的定时器还是开启了

进阶版

解决基础版无法自动停止的问题也很简单,加一个变量来检测,一旦执行了stop方法不返回定时器就可以了

// 可以自动停止的定时器
function myInterval(callback, interval = 2000) {
    let timer
    let isStop = false
    const stop = () => {
      console.log("停止")
      isStop = true
      clearTimeout(timer)
    }
    const start = () => {
      isStop = false
      loop()
    }
    const loop = async () => {
      callback()
      if (isStop) return
      return (timer = setTimeout(loop, interval))
    }
    return {
      start,
      stop
    }
  }

下面把main方法再改一改

function main() {
    const flag = parseInt(Math.random() * 2) === 1
    console.log("flag", flag)
    return flag ? Promise.resolve() : Promise.reject()
}

main方法这次返回的是Promise,我们来看看执行的情况

进阶版还是不支持main中有Promise的情况,我们希望的是,当main中出现Promise reject和错误的时候,中止轮询

最终版

asyncawait可以实现main方法中出现错误的时候中止轮询

function myInterval(callback, interval = 2000) {
    let timer
    let isStop = false
    const stop = () => {
      console.log("停止")
      isStop = true
      clearTimeout(timer)
    }
    const start = async () => {
      isStop = false
      await loop()
    }
    const loop = async () => {
      try {
        await callback(stop)
      } catch (err) {
        console.error("轮询出错:", err)
        throw new Error("轮询出错:", err)
      }
      if (isStop) return
      return (timer = setTimeout(loop, interval))
    }
    return {
      start,
      stop
    }
  }

可以看到最终版能满足我们的轮询要求了,遇到接口报错的时候可以终止请求,细心的您应该能发现这行代码 callback(stop),是的,main中现在多了一个回调方法,可以直接调用该方法停止轮询

main再次改回来

let count = 0
function main(stop) {
    count += 1
    console.log("count:", count)
    if (count == 5) {
      stop()
    }
}

可以看到,调用stop也是可以中止轮询的

现在一个完美的js可终止轮询请求,interval就完成啦~

到此这篇关于用Javascript实现可终止的轮询请求的文章就介绍到这了,更多相关js轮询请求内容请搜索编程笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程笔记!


推荐阅读
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • FineReport平台数据分析图表显示部分系列接口的应用场景和实现思路
    本文介绍了FineReport平台数据分析图表显示部分系列接口的应用场景和实现思路。当图表系列较多时,用户希望可以自己设置哪些系列显示,哪些系列不显示。通过调用FR.Chart.WebUtils.getChart("chartID").getChartWithIndex(chartIndex).setSeriesVisible()接口,可以获取需要显示的系列图表对象,并在表单中显示这些系列。本文以决策报表为例,详细介绍了实现方法,并给出了示例。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 在JavaScript中,函数没有重载的概念,如果声明了多个重名的函数,不管函数的形参个数是否一样,只有最后一个有效。如果调用函数时传入的参数个数与函数定义时的参数个数不符,会出现不同的情况。函数调用时,传入的参数个数少于函数定义时的参数个数,未传入的参数会被当做undefined处理,可能会导致错误。而传入的参数个数多于函数定义时的参数个数,多余的参数不会被使用,但不会报错。 ... [详细]
author-avatar
瘦哆哆和胖大雄
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有