1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

addEventListenerにより重複している処理を防ぐ方法

Posted at

動作環境
Ruby 2.6.5
Rails 6.0.3.2

以前、addEventListenerによって同じ処理が何度も発生していたことにより、エラーが起きてしまい、思うような処理ができないことがあったので、投稿してみました。

##addEventListenerにより重複している処理が発生してしまう例

index.html.erb
<% @hugas.each do |huga| %>
  <div class="huga" >    
    <%= huga.content %>
  </div>
<% end %>

上記のコードは、hugaのcontentカラムを繰り返し表示させており、その表示されたcontentのclassはhugaであるということを表しています。

huga.js
function hoge() {
  const hugas = document.querySelectorAll(".huga");
  hugas.forEach(function (huga) {
    huga.addEventListener("click", () => {
    //クリックすることで発生する処理
    });
  });
};
setInterval(hoge, 1000);

function hoge()を1行目として、2行目からこのコードの解説をしていきます。
2行目でclassがhugaである要素をすべてhugasに代入しています。
3行目でhugasを1つずつに分けて、それらの名前をhugaとしています。
4行目でhugaをクリックすると5行目の処理を発生するようにしています。
最終行により、以上の動作を毎秒発生させています。

つまり、上記の2つのコードはcontentをクリックすると、huga.jsの5行目に書かれた処理が発生するということを表しています。

しかし、このままではエラーが起きてしまいます。なぜなら、huga.jsの最終行により毎秒2行目と3行目の動作が発生しているからです。それによって何が起こるのかというと、例えばそのページに遷移してから10秒後にcontentをクリックした場合、5行目の処理が10回同時に発生してしまうというようなことが起きてしまいます。

この問題を解決するために、この記事のタイトルである「addEventListenerにより重複している処理を防ぐ方法」が必要となります。

※そもそもsetIntervalではなく、window.addEventListener('load',hoge);にすれば良いのではという意見が出ると思いますが、その通りです。しかし、index.html.erbのhuga.contentにおいて非同期通信が使われている場合はsetIntervalを使う必要があります。非同期通信だとページのロードが行われないからです。

##addEventListenerにより重複している処理を防ぐ方法

huga.js
function hoge() {
  const hugas = document.querySelectorAll(".huga");
  hugas.forEach(function (huga) {
    if (huga.getAttribute("baz") != null) {
      return null;
    }
    huga.setAttribute("baz", "true");
    huga.addEventListener("click", () => {
    //クリックすることで発生する処理
    });
  });
};
setInterval(hoge, 1000);

重複している処理は、上記のコードの4行目から7行目を追記することで防ぐことができる。なぜなら、この追記によって何秒経過してからcontentをクリックしても、1つのhugaには1回の処理しか行わないという意味になるからです。

追記した部分を詳しく解説していきます。
まず、1秒経過すると1回目の処理が行われ、if文によって条件分岐が起きます。hugaはbazという属性(Attribute)は持っていないのでnullとなり、条件式はfalseとなりますが、falseの場合の処理は記載されていないため、そのまま次の処理に移ります。7行目によって、hugaにbazという属性が与えられ、それはtrueとなります。つまり、1回目の処理は記載する前と変わっていません。

2秒経過した場合を見ていきます。2秒経過すると2回目の処理が行われ、再度if文によって条件分岐が起きます。1回目と違い、hugaにはbazという属性を持っているため、nullではありません。そのため、条件式はtrueとなり、trueの場合の処理が行われ、return nullが実行されます。return nullとは、処理を抜け出すという意味なので、この記載以降の処理は行われなくなります。つまり、2秒経過してから、contentをクリックしても、処理が1回しか行われないようになります。
当然ですが3秒後以降も同じであるため、重複している処理を防ぐことができます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?