当前位置: 首页 > news >正文

前端竞态问题是什么?怎么解决?

前端竞态问题

  • say在前面的
  • 什么是竞态问题
    • 核心代码
    • 效果展示
  • 使用await可以解决吗?
  • 解决方法
    • 方法一
    • 方法二

say在前面的

  • 之前波煮在学习promise的时候尚硅谷的网课中有讲,但是实在有些久远了,导致波煮今天看到竞态问题的时候都不知道它的意思,所以今天这篇博客就当提醒自己!

什么是竞态问题

  • 前端竞态问题的来源主要是网络请求的异步特点,两次或者多次网络请求同时在等待响应(也就是pending状态),由于异步是不知道响应顺序的,所有就会导致最终状态可能出乎了你的意料。
  • 比如我这里用promise + settimeout以及随机数给大家模拟一下:这里我用两个按钮分别表示页面1和页面2,由于在项目中我们页面的数据一般都是网络请求得到然后动态渲染的,所以在快速切换页面时可能会出现前一个请求还未响应,第二个响应了,此时数据已经渲染了,接着第一个请求响应,于是页面数据会再次变化

核心代码

btn1.addEventListener("click", () => {randomDelay = Math.floor(Math.random() * 2000);// 使用 setTimeout 模拟异步操作new Promise((resolve, reject) => {setTimeout(() => {resolve("页面1");}, randomDelay);}).then((res) => {currentPage.textContent = res;console.log("页面一数据返回")});});btn2.addEventListener("click", () => {randomDelay = Math.floor(Math.random() * 2000);// 使用 setTimeout 模拟异步操作new Promise((resolve, reject) => {setTimeout(() => {resolve("页面2");}, randomDelay);}).then((res) => {currentPage.textContent = res;console.log("页面二数据返回")});});

效果展示

  • 这里我一共点了三次按钮
  • 第一次:点击了页面1按钮
  • 第二次:点击了页面2按钮
  • 第三次:点击了页面1按钮
  • 按照我们的期待的效果应该是:最后的页面应该是页面1,但是这里确是页面2,这就是所谓的竞态问题
    在这里插入图片描述

使用await可以解决吗?

  • 写这篇的时候本人突然想到”诶,await不就是要等到响应后才会进行下一步操作吗“,那它可以解决我刚刚说的竞态问题吗?
  • 答案当然是不能了,await只能保证”当前函数内部按照顺序执行“,多次独立事件产生的异步任务仍然可能交叉完成。

解决方法

  • OK,现在我们知道了是什么是竞态问题,那么我们来讲讲解决方法。
  • 我们很容易就能想到一种方案,就是只执行我们最后一次的请求,之前的请求我们手动给他们撤销,我们知道fetch或者axios里面都封装了请求取消的方法,这时候我们就可以用到他们。
  • 第二种方案就是给每一个请求加入一个唯一id,收到请求响应之后只处理最新id的请求,将其他请求选择性忽略。

方法一

  • 因为这里我用到的是promise模拟,所以我们需要用到AbortController,自己来封装一个可以取消的promise,代码如下:
  // 创建可取消的 Promisefunction createCancellableRequest(pageName, delay) {return new Promise((resolve, reject) => {// 创建新的 AbortControllerconst controller = new AbortController();const signal = controller.signal;// 如果已经有请求在进行中,取消它if (currentController) {currentController.abort();}currentController = controller;// 监听取消信号signal.addEventListener('abort', () => {reject(new Error('请求被取消'));});// 模拟异步操作setTimeout(() => {// 检查是否被取消if (signal.aborted) {reject(new Error('请求被取消'));return;}resolve(pageName);}, delay);});}
  • 接着使用这是封装好的promise进行模拟请求,就可以解决竞态问题了。

方法二

  • 第二种方法就是使用唯一id标识每个模拟请求,只处理最后一次请求的方法
  • 代码如下:
    	// 用于存储当前有效的请求IDlet currentRequestId = 0;// 创建带唯一ID的请求function createRequestWithId(pageName, delay) {// 生成新的请求IDconst requestId = ++currentRequestId;return new Promise((resolve) => {setTimeout(() => {resolve({ pageName, requestId });}, delay);});}
  • 最后也可以成功解决竞态问题!
http://www.dtcms.com/a/524472.html

相关文章:

  • 问题记录--elementui中el-form初始化表单resetFields()方法使用时出现的问题
  • 运用jieba库解决词频分析问题
  • 【Linux】自动化构建工具--make/Makefile
  • 乡镇网站建设工作计划商城网站支付端怎么做
  • 咸阳网站开发公司电话seo网站关键词排名优化公司
  • 八股文面试题(全栈所有)
  • Mac Studio 和 DGX Spark 可用性分析
  • 【小白笔记】「while」在程序语言中的角色
  • 网站推广员怎么做怎么投诉网站制作公司
  • Flexbox 与定位结合-实现更复杂布局
  • 基于随机森林算法的Boss直聘数据分析及可视化-hadoop+django+spider
  • 最适合seo的网站源码专门做网页的网站
  • 企业微信机器人配置webhook自动推送错误订单信息
  • Web3 前端与合约交互
  • 基于window/ubuntu安装rknn-toolkit2【docker】
  • Mac安装配置MySQL
  • JumpServer堡垒机的安装部署
  • Harmony鸿蒙开发0基础入门到精通Day05--JavaScript篇
  • 福州医疗网站建设电商平台管理系统
  • 【乐鑫】乐鑫平台库文件生成方法
  • 文件IO操作
  • GStreamer视频编码
  • 【Go】--闭包
  • 正规网店代运营公司seo难不难
  • 【Dataset】如何高效处理海量数据并从中智能筛选出有代表性的样本?
  • 攻防世界-Web-Confusion1
  • python:怎样用 Django 开发电子商务程序
  • 【u-boot】u-boot驱动模型-struct uclass_driver
  • 昌吉网站建设公司怎么用php安装wordpress
  • 山西网站建设营销什么价格html模板在哪找