This is the 26th day of my participation in the August Text Challenge.More challenges in August

preface

I met a problem today. The scene of my project is that there is a button on the page, and the button can be switched. After the switch, the content at the bottom will be switched, but this content is the data returned by the background.

If I switch buttons faster and the interface that requested them first returns more slowly than the interface that requested them later, it will cause the content returned by the interface that requested them first to be displayed below the button that requested them later, resulting in inconsistency.

Scene: the repetition

Here’s a code to simulate:

  <div>
    <button>button 1</button>
    <button>button 2</button>
    <button>button 3</button>
  </div>
  <div class="content">content:</div>
  <script>
    const buttonList = document.querySelectorAll('button')
    const contentDom = document.querySelector('.content')
    const content = contentDom.innerText

    buttonList.forEach((item, i) = > {
      item.addEventListener('click'.() = > {
        const index = i + 1
        if (item.innerText === 'button 1') {
          setTimeout(() = > {
            freshContent(item, index)
          }, 2000)}else if (item.innerText === 'button 2') {
          setTimeout(() = > {
            freshContent(item, index)
          }, 500)}else {
          freshContent(item, index)
        }
      })
    })
    function freshContent(index) {
      contentDom.innerText = content + ' ' + index
    }
  </script>
Copy the code

Resolution:

Here, I use setTimeout to simulate the return speed of the interface. Click Button1 to refresh the content after 2000ms, click Button2 to refresh the content after 500ms, and click Button3 to refresh the content directly.

The effect is as follows:

As you can see, I’ll click the first button, click the second button, but since the first refresh button is in 2000 ms, is I click the second button and the second button to refresh the content of the before trigger, lead to give covers the contents of the second button, click the second button, and then show the contents of the first button.

So what’s the solution?

Problem solving

The first way

Solve by recording the number of times.

Each time the button is clicked, record the number of times (times plus one), and then save the current number of times to the clicked button. When refreshing the content, see whether the number of times recorded is equal to the number of times of the current button. If they are equal, the last trigger is proved and the content can be refreshed.

The code is as follows:

  <div>
    <button>button 1</button>
    <button>button 2</button>
    <button>button 3</button>
  </div>
  <div class="content">content:</div>
  <script>
    const buttonList = document.querySelectorAll('button')
    const contentDom = document.querySelector('.content')
    const content = contentDom.innerText
    // The number of times recorded
    let count = 0
    buttonList.forEach((item, i) = > {
      item.addEventListener('click'.() = > {
        // Add one
        count++
        // Save the current count in the current button
        item.count = count
        const index = i + 1
        if (item.innerText === 'button 1') {
          setTimeout(() = > {
            freshContent(item, index)
          }, 2000)}else if (item.innerText === 'button 2') {
          setTimeout(() = > {
            freshContent(item, index)
          }, 500)}else {
          freshContent(item, index)
        }
      })
    })
    function freshContent(item, index) {
      // Determine whether the number of times of the current button is equal to the number of times of the record
      if (item.count === count) {
        contentDom.innerText = content + ' ' + index
      }
    }
  </script>
Copy the code

And you can see that no matter what the point is, it’s the same thing.

The second way

This can be done by interrupting the request.

When we click the next button, the request for the previous button is broken. XMLHttpRequest is implemented through abort, and axios is implemented through cancelToken.

However, this method does not determine whether the request has been sent to the background, so it may fail to interrupt.

The third way

You can display loading animations until the request is returned and the next button can be clicked.

When we click the button, a loading animation is added after the request is made, and then the button cannot be clicked until the loading is removed after the request succeeds or fails, and then the button can be clicked, and so on.

conclusion

This is I encountered in the development of button switch race problem, this kind of problem is very common, we record, after encounter know how to solve this problem.

Thank you for reading.