

以下のような処理があったとき、重い処理は`setTimeout`で処理すべきでしょうか？

[code]

    $(document).bind("keydown keyup",function(e){
        if (e.type === "keydown"){
            ... //重い処理
        }
        if (e.type === "keyup"){
            ... //別の処理
        }
    });
    
[/code]

つまり、このようにすべきでしょうか？

[code]

    $(document).bind("keydown keyup",function(e){
        if (e.type === "keydown"){
            setTimeout(function(param1,param2){
                ... //重い処理
            },0,prm1,prm2);
        }
        if (e.type === "keyup"){
            ... //別の処理
        }
    });
    
[/code]

あるキーが`keydown`されたら重い処理を行い、`keyup`されたら別の軽い処理を行っているのですが、重い処理が途中で終わってしまっている気がします。  
実際には、undo処理みたいなことを`ctrl+Z`を`keydown`でやってるんですが、途中で終わっているというか、長く`keydown`するとちゃんと動くような感じで困ってます。  
重い処理といっても、何秒もかかるようなものではありません。せいぜい長くて数百ミリ秒～1秒だとおもいます。

いかんせん、ここ最近JavaScriptもjQueryも始めたため、ちゃんと理解出来ていないと思います。宜しくお願いします。

* * *

捕捉します。重い処理で行った結果を受けて、別の処理を行います。  
実際にはundoを行うとブラウザ上の要素のサイズ等変更を元に戻す、そのようにしようとしています。

* * *

分かりづらいので、捕捉します。  
上記の処理で、`keydown`と`keyup`とは、処理を共有していますが、`keydown`と`keyup`でイベントを引いている無名関数はそれぞれ別々に非同期処理されているのだと思っています。ただ、わたしはJavaScriptを使って間もないのでその辺の理解が間違っているかもしれません。

`keydown`され、重い処理がはじまって`keyup`されるまでに処理が終わらず、それでおかしなことが起きているのだろうかと思っています。

もし、そのばあい`keydown`側の重い処理が終了してから`keyup`の処理を行わせる(`keyup`が完了していてキー操作とずれても構わないので)といいますか適切に待つ処理が必要なら、御教示いただけると助かります。

JavaScriptではクリティカルセクションのような仕組みはないかと調べていましたが、ローカル側でそんなことをしちゃいけないのでしょうか？


CC BY-SA 3.0
2016-03-03T12:02:41.333
22766
2019-12-13T18:54:56.560
2016-03-03T14:43:59.053
7966
7966
question
javascript jquery 非同期
JavaScript(jQuery)でkeydown,keyup等のイベントで重い処理をするときsetTimeoutすべき？


良い記事があったので紹介します。

[JavaScriptの同期、非同期、コールバック、プロミス辺りを整理してみる -
Qiita](http://qiita.com/YoshikiNakamura/items/732ded26c85a7f771a27)

> 大前提として、JavaScriptはシングルスレッドで動いています。  
>  これはつまり、JavaScriptは並行処理はできないということです。

よって、`keydownの重い処理`が、終わるまで、`keyup` の処理は走らないものと思います。(setTimeout
などを使い、割り込みを許しているなら別なのですが)

[code]

    var c = 0
    $(document).bind("keydown keyup", function(e) {
      $console = $("#console")
      c += 1
      if (e.type === "keydown") {
        start = end = new Date().getTime()
        while (end - start < 1000) {
          end = new Date().getTime()
        }
        $console.append(e.type + ": " + c + "<br>")
      }
      if (e.type === "keyup") {
        $console.append(e.type + ": " + c + "<br>")
      }
    })
[/code]

[code]

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
    Event Console
    <div id="console">
    </div>
[/code]

keydown と keyup の順番を確認するテストをしてみましたが、keydown の後に keyup が走りました。  
keydown で1秒待つ、というものです。。


CC BY-SA 4.0
2016-03-03T14:30:34.797
22772
2019-12-13T18:54:56.560
2019-12-13T18:54:56.560
32986
7471
22766
answer


おそらく同時に非同期処理を行うものが複数あり、どのメソッドの`callback`で完了すればよいか分からないパターンかと推測しました。

複数の非同期処理を同時に動かして、その完了を待つには`$.Deferred`、`$.when`を使います。

一応例を示しますが、何をどうしているのか分からないのでとりあえず完了時間の違う複数の`animate`の一番時間がかかるアニメーションが完了するまで待つような処理にしています。

例のような処理をしたい場合、`keydown`と`keyup`で分けるより`keyup`だけを取って`keydown`相当の処理と`keyup`相当の処理をメソッド化して`keyup`イベントの発火時に処理すれば良いと思います。

[code]

    $(document).ready(function() {
    
      $(document).on('keyup',function(e){
    
        // keydown処理を待ってkeyup処理を行う
        $.when(
          keydownProcess()
        ).done(
          keyupProcess
        );
      });
    
      $('input').on('click', function(){
        $('.target').width(300).height(50).text('');
      });
    });
      
    // keydown処理相当  
    // 完了する時間がバラバラな非同期処理で一番処理時間が長いものが終わってから完了を返す
    function keydownProcess()
    {
      $('#target1').text('keydown process');
      var d = new $.Deferred;
      $.when(
        // ここに非同期メソッドをかく
        $('#target1').stop().animate({width:150}, 500),
        $('#target2').stop().animate({width:150}, 1000)
      ).done(function(){
        d.resolve();
      });
      return d.promise();
    }
    
    // keyup処理相当  
    function keyupProcess()
    {
      $('#target1').text('keyup process');
    }
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    
    <input type="button" value="戻す" />
    <div id="target1" class="target" style="background: #aaffff; width: 300px; height: 50px"></div>
    <div id="target2" class="target" style="background: #aaffaa; width: 300px; height: 50px"></div>
[/code]

参考URL：  
<http://techblog.yahoo.co.jp/programming/jquery-deferred/>  
<http://qiita.com/yuku_t/items/1b8ce6bba133a7eaeb23>


CC BY-SA 3.0
2016-03-04T03:21:14.963
22783
2016-03-04T03:29:16.020
2016-03-04T03:29:16.020
7214
7214
22766
answer