竞态条件(Race condition)

更新日期: 2023-10-19阅读: 709标签: 条件

什么是竞态条件?

当你的程序依赖正确的响应顺序,但响应的顺序又无法保证时,可能会导致意外的结果,这就是竞态条件。

举个用户界面的例子:

在上图中,分别点击科技和生活tab时,期望能够展示对应的数据

我们来设想如下情况:

  1. 点击科技按钮(高亮科技按钮)(数据2秒后返回)
  2. 点击生活按钮(高亮生活按钮)(数据1秒后返回)
    最终,展示区域会在1秒后显示生活数据,2秒后展示科技数据,但此时,我们的按钮会高亮会在生活上,但我们的展示区域显示的却是科技数据。也就是高亮的按钮和展示数据不同步,这就是竞态条件造成的问题。


如何避免?

方案1:每次操作完成之前,阻止新的操作

这个方案用的比较普遍,具体思路就是请求发生期间,添加一个loading遮罩层,这样在当前请求响应之前,后续的操作都会被loading遮罩层避免掉,也就不会有竞态问题的发生。

方案2:每次发送请求时,丢掉上一个请求的响应

该方案的思路是,在响应完成之前,如果用户有新的请求,那就丢弃掉未完成的请求,其结果就是只对最新的请求进行响应,也就避免出现旧的请求响应数据展示在了当前高亮视图下。

function getResolveWhenLast() {
    let globalId = 0;

    return (pro) => {
      return new Promise((resolve, reject) => {
        const id = ++globalId;

        pro
          .then((res) => {
            if (id === globalId) {
                resolve(res);
            }
          })
          .catch(err => {
            if (id === globalId) {
                reject(err);
            }
          })
      })
    }
}

const resolveWhenLast = getResolveWhenLast()

// 使用resolveWhenLast包住你的请求,就可以解决竞态问题
resolveWhenLast(api.getPosts()).then(res => {
    // ...
})

方案3:每次发送请求时,取消掉上一次的请求

给promise加了一层包装,添加了cancel的能力,每次请求发出的时候,将上一次的请求取消掉,同样达到了只最处理最新一次请求响应的目的,也就避免了竞态条件的发生。

// 给Promise添加取消请求的能力
function createImpretivePromise(pro) {
  let resolve = null;
  let reject = null;

  const warppedPromise = new Promise((_resolve, _reject) => {
      resolve = _resolve;
      reject = _reject;
  })

   pro
    .then((res) => {
      resolve && resolve(res);
    })
    .catch((err) => {
      reject && reject(err);
    });

  // 可以切断代理
  const cancel = () => {
    resolve = null;
    reject = null;
  }

  return {
    promise: warppedPromise,
    cancel
  }
}

const getResolveWhenLast = () => {
  let globalCancel = null;

  return (pro) => {
    const { promise, cancel } = createImperativePromise(pro);

    globalCancel && globalCancel();
    globalCancel = cancel;

    return promise;
  };
};

const resolveWhenLast = getResolveWhenLast()

// 使用resolveWhenLast包住你的请求,就可以解决竞态问题
resolveWhenLast(api.getPosts()).then((res) => {
    // ...
});
原文:https://segmentfault.com/a/1190000044313008

链接: https://fly63.com/article/detial/12535

JavaScript条件判断: Js三元运算符介绍

运用条件运算符将你的 if 语句缩短为一行代码,运用条件语句,比如 if,当 if 语句满足的情况下,允许我们执行指定一些代码块...

HTML条件注释_关于IE条件注释

就是在每个浏览器中上边两个中只能使用一个的话一定得记得把IE9考虑进来,因为它也是能识别条件注释的(感觉IE9就是IE向现代高级浏览器过渡的东西,CSS3只支持一部分,但是之前IE专有的一些问题照样存在)

css3条件判断_@supports的用法/Window.CSS.supports()的使用

为了判断浏览器是否支持css3的一些新属性样式,当不兼容该样式的时候,我们可以更优雅的降级处理。这就需要使用到css3的条件判断功能:在css中支持@supports标记、或者在js中使用CSS.supports函数,来检测浏览器是否支持css3的新属性。

js条件判断语句优化

在js中的条件判断,主要用于不同的条件执行不同的动作,实际开发中,我们如何实现js条件判断语句优化的呢?1、一个条件推荐用if else或者三元运算,2、当2个条件是用if...elseif...else...3、三个条件及以上时候推荐用switch

写好JavaScript条件语句的5个技巧

当我们写JavaScript代码时,经常会用到到条件判断处理,这里有5个技巧能使你写出更好、更简洁的条件语句。使用Array.includes处理多种条件、减少嵌套,尽早return、使用函数默认参数和解构

js中的if判断语句和switch条件分支语句

语句是js中最重要的成分。本文想介绍的是if判断语句和switch条件分支语句,如果不加入break会默认从满足条件一直向下执行.最后的default就是相当于if条件语句中的else,switch语句用的是全等判断,大家一定要注意一下

Vue条件判断

在Vue进行前端开发中,条件判断主要用于根据不同的条件来决定显示或隐藏,或者进行视图之间的切换,本文以一个简单的小例子简述v-if的常见用法,仅供学习分享使用

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!