57655


クリックイベントで呼び出した関数の処理が全て終わってから、クリックイベント内の関数呼び出し後の処理をさせるにはどうしたらよいでしょうか。

* * *

## 現状

`close`ボタンを押したら、`outMotion`の処理が終わってから`viewArea`という要素を非表示にする、という処理を行いたく下記のコードを書いています。

[code]

    $("#close").on("click", () => {
        outMotion();
        $("#viewArea").hide(); // outMotion関数の処理が終わってから実行したい
    });
    
    const outMotion = () => {
        // モーション処理
    };
    
[/code]

* * *

## 問題点

しかし、上記のコードだとモーションが終わるのを待たずして、`viewArea`要素が非表示になります。  
このような処理になる理由は、「JavaScriptは非同期処理だから」というのは理解しています。

* * *

## 調べたこと

同期処理をさせるにはコールバックするとよい、ということが調べて分かりました。  
そこで、コールバックについて調べました。

下記のページ  
<https://www.sejuku.net/blog/52314#Promise>

で、コールバックの使用例を見つけたのですが、例のコードの意味が私では理解できず、自身のコードに置き換えることができませんでした。  
使用例のコードのキャプチャを載せます。

[![画像の説明をここに入力](https://i.stack.imgur.com/Y8YjZ.jpg)](https://i.stack.imgur.com/Y8YjZ.jpg)

上図のコードで私が理解できなかったポイントは、`getData`関数内で呼び出している関数名の（）が無い状態を、`getData`関数の引数に記述している点です。  
「値や別のスコープで生成や使用されオブジェクトを受け取るもの」というのが、私の現状の引数の認識です。

この認識で、引数を使用した処理例を下記に書きます。

[code]

    const a = () => {
        const aObj = 1;
        b(aObj);
    　　// aObjをb関数で使用するため、b関数を呼び出すと同時に引数としてaObjを渡す。
    };
    
    cosnt b = aObj => { // 引数aObjを受け取る。
       console.log(aObj); // 受け取ったaObjを使用する。
    }
    
[/code]

私がいま作っているプログラムで上記のような書き方を部分的に使用しておりまして、希望通りの挙動をしています。  
なので私の引数の認識は「引数の理解を完全にできていないが、間違っているとは言えない」ぐらいのものかと思われます。  
ただ、例に示めされているコードで動くわけなので、私の理解が足りない、ならびに間違っていることも認識しております。

以上の私の認識および認識レベルですと、「引数に関数内で呼び出す関数名を書く」意味が分かりませんでした。

くどいようですが先に述べた通りの私の認識ですと、上図の下の`getData`関数を呼び出すコードも下記の点で理解ができませんでした。

・`getData`関数を呼び出す際に、引数として関数を渡している  
・`funciton(data){ getYear(data); }`の`data`はどこから来たのか  
・`funciton(data)`で`getYear`を呼び出しているが、`getYear`関数はどこから来たのか（またはどこで定義されているのか）

* * *

## 長々と書きましたが、

本題は、 **現状** の項にあるコードで起きている問題を、冒頭文にある処理にするにはどうしたらよいでしょうか、です。

* * *

## コード（追記）

[code]

    $("#view").on("click", () => {
        $("#viewArea").show();
        inMotion();
    });
    
    $("#close").on("click", () => {
        outMotion();
        $("#viewArea").hide();
    });
    
    const inMotion = () => {
        anime({
            targets: "li",
            translateY: ["100%", "0%"]
        });
    };
    const outMotion = () => {
        anime({
            targets: "li",
            translateY: ["0%", "100%"]
        });
    };
[/code]

[code]

    body {
        max-width: 500px;
        width: 100%;
        margin: auto;
        text-align: center;
    }
    
    #viewArea {
        display: none;
    }
    
    ul {
        padding-left: 0;
        list-style: none;
        display: flex;
    }
    
    li {
        margin: 0 5%
    }
[/code]

[code]

        <body>
            <button id="view">表示</button>
            <div id="viewArea">
                <ul>
                    <li><button>a</button></li>
                    <li><button>b</button></li>
                    <li><button>c</button></li>
                    <li><button>d</button></li>
                    <li><button>e</button></li>
                    <li><button id="close">close</button></li>
                </ul>
            </div>
    
            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script>
        </body>
[/code]


CC BY-SA 4.0
2019-08-27T15:46:27.383
57640
2019-08-28T06:07:28.580
2019-08-27T23:54:19.143
35433
35433
question
javascript jquery
クリックイベントA内で呼び出した関数の処理が終わってから、Aの続きの処理を行う方法を教えてください。


こんな感じになるでしょうか?

[code]

    const outMotion = function(callback) {
        // モーション処理
        //...
        callback();
    };
    
    $("#close").on("click", function() {
        outMotion(function() {
            $("#viewArea").hide(); // outMotion関数の処理が終わってから実行したい
        });
    });
[/code]

[code]

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <button id="close">Close</button>
    <div id="viewArea" style="background-color: red">viewArea</div>
[/code]

* * *

「調べたこと」を読む限り、関数の引数についても理解が不十分ですし、「関数そのものを渡すこと」と「関数を呼び出してその結果を使うこと」の区別が全くついていないように思います。

(上記の例では、より強く「関数そのもの」を扱っている感が出るかと思って、アロー記法を使わずに無名関数の構文を使っています。)

とりあえず、「関数そのものを渡すこと」の簡単な例を書いてみますので、よく理解できない部分があれば、コメント等でお知らせください。

[code]

    //関数を定義する
    function test(data) {
        alert(data);
        return "value";
    }
    //定義した関数を実行する
    test("引数");
    //定義した関数を変数に入れる
    var f = test;
    //変数に入っている関数を実行する
    f("argument");
    //変数に別の無名関数を代入する
    f = function(data) {
        alert(data);
        return data + data;
    }
    //変数に入っている関数を実行した結果をさらに別の変数に代入
    var g = f("param");
    alert(g);
[/code]


CC BY-SA 4.0
2019-08-27T18:35:41.390
57642
2019-08-27T18:35:41.390
13972
57640
answer


JavaScriptのすべてが非同期というわけではなくて、この場合`anime()`の処理がたまたま非同期なのです。こういった非同期処理には多くの場合終了時に呼ばれるコールバックが用意されています。

<https://tr.you84815.space/animejs/callback.html>

`outMotion()`にコールバックを渡す必要がありますね。

[code]

    $("#close").on("click", () => {
        outMotion(() => {
          $("#viewArea").hide();
        });
    });
    
    const outMotion = callback => {
        anime({
            targets: "li",
            translateY: ["0%", "100%"],
            complete: callback
        });
    };
    
[/code]

また、anime()は`Promise`を提供しているようなので、`await`を使うこともできます。  
<https://tr.you84815.space/animejs/promises.html>

[code]

    $("#close").on("click", async () => {
        await outMotion();
        $("#viewArea").hide();
    });
    
    const outMotion = () => {
        return anime({
            targets: "li",
            translateY: ["0%", "100%"],
        }).finished;
    };
    
[/code]


CC BY-SA 4.0
2019-08-28T06:07:28.580
57655
2019-08-28T06:07:28.580
3475
57640
answer