首页 > 其他分享 >记录--前端中 JS 发起的请求可以暂停吗

记录--前端中 JS 发起的请求可以暂停吗

时间:2023-12-11 20:13:58浏览次数:23  
标签:控制器 请求 -- 前端 JS controller Promise result 暂停

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

在前端中,JavaScript(JS)可以使用XMLHttpRequest对象或fetch API来发起网络请求。然而,JavaScript本身并没有提供直接的方法来暂停请求的执行。一旦请求被发送,它会继续执行并等待响应。

尽管如此,你可以通过一些技巧或库来模拟请求的暂停和继续执行。下面是一种常见的方法:

1. 使用XMLHttpRequest对象

你可以在发送请求前创建一个XMLHttpRequest对象,并将其保存在变量中。然后,在需要暂停请求时,调用该对象的abort()方法来中止请求。当需要继续执行请求时,可以重新创建一个新的XMLHttpRequest对象并发起请求。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/api', true);
xhr.send();

// 暂停请求
xhr.abort();

// 继续请求
xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/api', true);
xhr.send();

2. 使用fetch API和AbortController

fetch API与AbortController一起使用可以更方便地控制请求的暂停和继续执行。AbortController提供了一个abort()方法,可以用于中止fetch请求。

var controller = new AbortController();

fetch('https://example.com/api', { signal: controller.signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

// 暂停请求
controller.abort();

// 继续请求
controller = new AbortController();

fetch('https://example.com/api', { signal: controller.signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

请注意,这些方法实际上是通过中止请求并重新发起新的请求来模拟暂停和继续执行的效果,并不能真正暂停正在进行的请求。

3. 曲线救国

模拟一个假暂停的功能,在前端的业务场景上,需要对这些数据进行处理之后渲染在界面上,如果我们能在请求发起之前增加一个控制器,在请求回来时,如果控制器为暂停状态则不处理数据,等待控制器恢复后再进行处理,也可以达到暂停的效果。

// 创建一个暂停控制器 Promise
function createPauseControllerPromise() {
  const result = {
    isPause: false, // 标记控制器是否处于暂停状态
    resolveWhenResume: false, // 表示在恢复时是否解析 Promise
    resolve(value) {}, // 解析 Promise 的占位函数
    pause() { // 暂停控制器的函数
      this.isPause = true;
    },
    resume() { // 恢复控制器的函数
      if (!this.isPause) return;
      this.isPause = false;
      if (this.resolveWhenResume) {
        this.resolve();
      }
    },
    promise: Promise.resolve(), // 初始为已解决状态的 Promise
  };

  const promise = new Promise((res) => {
    result.resolve = res; // 将解析函数与 Promise 关联
  });
  result.promise = promise; // 更新控制器中的 Promise 对象

  return result; // 返回控制器对象
}

function requestWithPauseControl(request) {
  const controller = createPauseControllerPromise(); // 创建暂停控制器对象

  const controlRequest = request() // 执行请求函数
    .then((data) => { // 请求成功回调
      if (!controller.isPause) controller.resolve(); // 如果控制器未暂停,则解析 Promise
      return data; // 返回请求结果
    })
    .finally(() => {
      controller.resolveWhenResume = true; // 标记在恢复时解析 Promise
    });

  const result = Promise.all([controlRequest, controller.promise]).then(
    (data) => {
      controller.resolve(); // 解析控制器的 Promise
      return data[0]; // 返回请求处理结果
    }
  );

  result.pause = controller.pause.bind(controller); // 将暂停函数绑定到结果 Promise 对象
  result.resume = controller.resume.bind(controller); // 将恢复函数绑定到结果 Promise 对象

  return result; // 返回添加了暂停控制功能的结果 Promise 对象
}

为什么需要创建两个promise

在requestWithPauseControl函数中,需要等待两个Promise对象解析:一个是请求处理的Promise,另一个是控制器的Promise。通过使用Promise.all方法,可以将这两个Promise对象组合成一个新的Promise,该新的Promise会在两个原始Promise都解析后才会解析。这样做的目的是确保在处理请求结果之前,暂停控制器的resolve方法被调用,以便在恢复时解析Promise。

因此,将请求处理的Promise和控制器的Promise放入一个Promise数组,并使用Promise.all等待它们都解析完成,可以确保在两个Promise都解析后再进行下一步操作,以实现预期的功能。

使用

const result = requestWithPauseControl(/*request fn*/).then((data) => {
    console.log(data)
})

if (Math.random() > 0.5) { result.pause() }

setTimeout(() => {
    result.resume()
}, 4000)

本文转载于:

https://juejin.cn/post/7310786521082560562

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

标签:控制器,请求,--,前端,JS,controller,Promise,result,暂停
From: https://www.cnblogs.com/smileZAZ/p/17895439.html

相关文章

  • Scheduler 【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/scheduler/index.html#schedulerCompletions-"waitforcompletion"barrierAPIsCPUSchedulerimplementationhintsforarchitecturespecificcodeCFSBandwidthControlDeadlineTaskSchedulingCFSSchedulerS......
  • 第一节 Kotlin基础
    Kotlin基础简介主要介绍:开发环境的搭建Kotlin基本语法Kotlin参考Kotlin源代码网址:https://github.com/JetBrains/kotlinKotlin官网:https://kotlinlang.orgKotlin官方参考文档:https://kotlinlang.org/docs/referencekotlin标准库:https://kotlinlang.org/api/latest/......
  • CPU调度器实现提示:针对特定体系结构代码【ChatGPT】
    https://www.kernel.org/doc/html/v6.6/scheduler/sched-arch.html《CPU调度器实现提示:针对特定体系结构代码》NickPiggin,2005上下文切换运行队列锁定默认情况下,调用switch_to体系结构函数时会锁定运行队列。除非switch_to需要获取运行队列锁,否则通常不会出现问题。这通......
  • javaweDay1补充
    1.<label>标签可以使label标签中所包含的任何区域都可以聚焦到一个点如果没有label则必须点击那个圆圈才可以选上,而若有点击男也可以选中。2.下图中value后跟的值表明勾选男的时候提交表单的提交为1若改为男则是男3select定义下拉列表,option定义列表项 4.<textarea>文本......
  • C 语言入门:如何编写 Hello World
    C语言简介C语言是由DennisRitchie于1972年在贝尔实验室创建的一种通用编程语言。尽管年代久远,它仍然是一款非常流行的语言。它之所以受欢迎的主要原因是它是计算机科学领域的基础语言之一。C语言与UNIX紧密相连,因为它被用于编写UNIX操作系统。为什么要学习C语言?......
  • 写几个有用的lambda
    List<String>list=Arrays.asList("app","ban","ora");//循环输出for(Strings:list){System.out.println(s);}list.forEach(System.out::println);//排序......
  • ARC168E
    题面给定长度为\(n\)的数列\(\{a_i\}\)和两个参数\(k,s\),将\(\{a_i\}\)划分成\(k\)段,最大化和\(\geqs\)的段数。\(1\leqk\leqn\leq250000,1\leqA_i\leq10^9,1\leqs\leq10^{15}\)。题解首先注意到如果当前划分的一段\(sum<s\),那么这种段的长度......
  • LOJ #3353. 「CEOI2020」象棋世界
    题面传送门什么缝合怪(以下默认判掉一步走到。Section1:P容易发现不会改变纵坐标,简单判断即可。Section2:R两步,两种方案。Section3:Q因为\(n\geqm\),所以直走两种方案,先斜着走再竖着走两种方案是一定有的。以下默认其先往左下走,往右下走翻转再做一遍就好了。如果......
  • Java学习之路(十五)
    Java学习之路(十五)1、Map集合1.1、Map集合概述和特点【理解】Map集合概述interfaceMap<K,V>K:键的类型;V:值的类型Map集合的特点双列集合,一个键对应一个值键不可以重复,值可以重复Map集合的基本使用publicclassMapDemo01{publicstaticvoidmain(Strin......
  • 武汉星起航打造共赢电商生态,合作伙伴实现共赢共生
     自2017年起,武汉星起航便踏上了亚马逊运营之路,凭借多家亚马逊自营店铺的独特优势,积累了丰富的运营经验。公司于2020年正式成立后,以跨境电商为核心,建立起专业的运营和服务团队,为合作伙伴提供全方位深入的合作模式。从店铺入驻、软件开通、运营指导到五对一咨询服务,星起航为合作伙......