質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

$.whenの非同期処理の関数化をすると.doneの処理が一部されない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 848

score 932

 前提・実現したいこと

$.whenの非同期処理を1つの関数にしたいです。

右からスライドして現れて、左にスライドしながら消えていくスライダーを作りました。

$.whenの非同期処理を1つの関数にすると.doneの一部である、
$('.current').css({'left': width});だけが実行されません。

1つの関数にするにはどのようにすればよいのでしょうか
ご教授お願いします。

 関数化する前のソースコード

<div class="container">
    <ul class="slide_wrap">
        <li class="current"><div style="background:#aff;">スライド1</div></li>
        <li class="nextSlide"><div style="background:#f00;">スライド2</div></li>
        <li><div style="background:#faf;">スライド3</div></li>
    </ul>
</div>
* {
    margin: 0;
    padding: 0;
}

li {
    list-style: none;
}

.container {
  width: 960px;
  height: 400px;
    margin: 50px auto 0;
}


.slide_wrap {
    width: 500px;
  height: 400px;
    margin: 0 auto;
  position: relative;
  overflow: hidden;
}

.slide_wrap li {
  position: absolute;
  top: 0;
  left: 100%;
}

.slide_wrap li.current {
  left: 0;
}

.slide_wrap div {
    width: 740px;
    height: 400px;
}
$(function() {
    function slidestart() {
        var slideItem = $('.slide_wrap li'); // スライドさせる全ての画像の取得
        var width = slideItem.width();  // 740: スライドさせる画像の幅
        var nextNum = 1; // 次にスライドする要素のindex番号
        var slideSet; // setIntervalのID

        // done時の処理
        function next() {
            if(nextNum == slideItem.length - 1) {
                nextNum = 0;
            } else {
                nextNum++;
            }
            $('.current').css({'left': width});  // 終ったスライド要素を初期位置に戻す
            $('.current').removeClass('current');
            $('.nextSlide').addClass('current');
            $('.nextSlide').removeClass('nextSlide');
            slideItem.eq(nextNum).addClass('nextSlide');  // 次の要素をスタンバイ
        }

        function slide() {
            // 非同期処理
            $.when( // 先の順番の処理
            $('.nextSlide').animate({left: 0},1500), // // 次をスライドイン
            $('.current').animate({left: - width},1500) // スライドアウト
            ).done(function() { // whenが終わったら実行
                next();
            });
        }

        slideSet = setInterval(function() {
            slide();
        },4000);

        setTimeout(function() {
            clearInterval(slideSet);
        },60000);

    } // slidestart

    slidestart();
});

 試したこと

1.普通に関数化
結果・・・.doneの処理が一部されない

    function current() {
        $('.nextSlide').animate({left: 0},1500); // // 次をスライドイン
        $('.current').animate({left: - width},1500); // スライドアウト
    }

    function slide() {
        // 非同期処理
        $.when( // 先の順番の処理
        current()
        ).done(function() { // whenが終わったら実行
            next();
        });
    }


2.DeferredとPromise
結果・・・動かない

    var current = function () {
        var d = $.Deferred();
        $('.nextSlide').animate({left: 0},1500); // // 次をスライドイン
        $('.current').animate({left: - width},1500); // スライドアウト
        return d.promise();
    };

    function slide() {
        // 非同期処理
        $.when( // 先の順番の処理
        current()
        ).done(function() { // whenが終わったら実行
            next();
        });
    }


3.非同期処理を別々の関数にしてreturnする
結果・・・動くのだが、そもそも1つの関数にしたいから他の方法を探す

     function first() {
        return $('.nextSlide').animate({left: 0},1500); // // 次をスライドイン
    };

     function second() {
        return $('.current').animate({left: - width},1500); // スライドアウト
    };

    function slide() {
        // 非同期処理
        $.when( // 先の順番の処理
        first(),
        second()
        ).done(function() { // whenが終わったら実行
            setTimeout(function() {
                next();
            },1000);
        });
    } // slide


4.1つの関数にして配列にしてreturnする
5..doneを遅延してみる
結果・・・.doneの処理が一部されない

    function current() {
        var obj = new Object();
        obj.val1 = $('.nextSlide').animate({left: 0},1500); // // 次をスライドイン
        obj.val2 = $('.current').animate({left: - width},1500); // スライドアウト
        return obj;
    };

    function slide() {
        // 非同期処理
        $.when( // 先の順番の処理
        current()
        ).done(function() { // whenが終わったら実行
            setTimeout(function() {
                next();
            },1000);
        });
    } // slide

 補足情報(FW/ツールのバージョンなど)

PC:win10
ブラウザ:chrome
jquery:1.12.4

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

単に関数内で$.when()を実行すれば解決します。

function current() {
  return $.when(
    $('.nextSlide').animate({left: 0},1500),
    $('.current').animate({left: - width},1500)
  );
}

//実行
current().done(function() {
  //両方のアニメーションが完了したときに呼び出される
  setTimeout(function() {
    next();
  },1000);
});

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/09 19:55

    ありがとうございます。
    無事解決して、理想通りになりました。

    キャンセル

+1

落とし所がどこなのかわからないのでなんともいえませんが
多分こういう事?

      function current() {
        return [
          $('.nextSlide').animate({left: 0},1500),
          $('.current').animate({left: - width},1500),
          ];
       }
      function slide() {
        $.when.apply(null,current()).done(function() {
          next();
        });
      }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/09 20:00

    ありがとうございます。
    回答者が二方いてyambejpさんの方法でも解決できるのを確認しました。

    先の回答者の方をベストアンサーにさせてもらいましたが、
    別パターンとして参考にさせてもらいます

    キャンセル

  • 2018/11/09 20:03

    slideからwhenの実行部分だけをcurrentとして独立させたいのかと思ったのですが
    どうやら違ったようですね、失礼しました

    キャンセル

  • 2018/11/09 20:29

    とんでもないです
    ありがとうございます。

    試したことの4つ目の正しい方法だと理解しました
    普通(っていうのでしょうか?)の配列にし、
    配列を受け取る場合はcall()ではなく、apply()で第二引数。
    とてもありがたい勉強になりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る