jQuery.Deferredを使って、xml読み込んでから他の処理を実行する方法

Javascript

前回の続きな感じですが、今回はxmlで内容を読み込んだあとに、それぞれの高さを合わせるために heightLine.jsを使うというお話です。

コード的に変な箇所がありましたらすみません。

高さを取得してみる

まずはxmlを読み込んだだけのコードです。それぞれのカラムには高さが解りやすいように青色の背景を、その親divには緑の背景を敷いてます。

$(function(){

    function textView01(){
        $.ajax({
            url: "xml01.xml",
            async: true,
            cache: false,
            dataType:"xml",
            success: function(xml){
                $(xml).find('text').each(function(){
                    var text = $(this).text();
                    $('.txt01').append('<p>' + text + '</p>');
                });
            }
        });
    }

    function textView02(){
        $.ajax({
            url: "xml02.xml",
            async: true,
            cache: false,
            dataType:"xml",
            success: function(xml){
                $(xml).find('text').each(function(){
                    var text = $(this).text();
                    $('.txt02').append('<p>' + text + '</p>');
                });
            }
        });
    }
    textView01();
    textView02();

	//高さ確認用
    var txt01Height = $('.txt01').height();
    var txt02Height = $('.txt02').height();
    $('.height01').append('1つめの高さ ' + txt01Height + 'px');
    $('.height02').append('2つめの高さ ' + txt02Height + 'px');

});

xmlは単純なものを2つ置いてます。

xml01.xml

<?xml version="1.0" encoding="utf-8"?>
<list>
    <text>テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1テキスト1</text>
	~中略~
</list>

xml02.xml

<?xml version="1.0" encoding="utf-8"?>
<list>
    <text>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Maxime voluptas sint id error voluptates, esse sit iste, adipisci maiores reprehenderit explicabo quibusdam voluptatem doloribus voluptatum vero laborum expedita fuga reiciendis?</text>
	~中略~
</list>

わかりやすいようにテキストが入っているboxの高さを取得してますが、0pxとなっているのがわかると思います。

そのまま記述してみる

先ほどのコードにそのまま試しに高さを合わせるheightLine実行のコードを足してみます。

$(function(){

    function textView01(){
        $.ajax({
            url: "xml01.xml",
            async: true,
            cache: false,
            dataType:"xml",
            success: function(xml){
                $(xml).find('text').each(function(){
                    var text = $(this).text();
                    $('.txt01').append('<p>' + text + '</p>');
                });
            }
        });
    }

    function textView02(){
        $.ajax({
            url: "xml02.xml",
            async: true,
            cache: false,
            dataType:"xml",
            success: function(xml){
                $(xml).find('text').each(function(){
                    var text = $(this).text();
                    $('.txt02').append('<p>' + text + '</p>');
                });
            }
        });
    }
    textView01();
    textView02();
    $(".bg > div").heightLine();

	//高さ確認用
    var txt01Height = $('.txt01').height();
    var txt02Height = $('.txt02').height();
    $('.height01').append('1つめの高さ ' + txt01Height + 'px');
    $('.height02').append('2つめの高さ ' + txt02Height + 'px');

});

この記述だとxmlが読み込んでからheightLineが実行されている訳ではないので、高さが全然ありません。その状態で高さを統一しているのでぺしゃんこな状態になっています。デモページはborderを引いてるので、高さが2pxと出ています。

xmlの読み込みが終わったの確認して実行する

なのでajaxの読み込みが完了した時に実行するようajaxにcompleteを追加し、そこに処理を移動します。

1つ目のajaxでxmlを読み込んだら2つ目のxmlを読み込んで高さを出しています。

$(function(){

    function textView01(){
        $.ajax({
            url: "xml01.xml",
            async: true,
            cache: false,
            dataType:"xml",
            success: function(xml){
                $(xml).find('text').each(function(){
                    var text = $(this).text();
                    $('.txt01').append('<p>' + text + '</p>');
                });
            },
            complete: function(){
                textView02();
            }
        });
    }

    function textView02(){
        $.ajax({
            url: "xml02.xml",
            async: true,
            cache: false,
            dataType:"xml",
            success: function(xml){
                $(xml).find('text').each(function(){
                    var text = $(this).text();
                    $('.txt02').append('<p>' + text + '</p>');
                });
            },
            complete: function(){
                $(".bg > div").heightLine();
                var txt01Height = $('.txt01').height();
                var txt02Height = $('.txt02').height();
                $('.height01').append('1つめの高さ ' + txt01Height + 'px');
                $('.height02').append('2つめの高さ ' + txt02Height + 'px');
            }
        });
    }
    textView01();

});

高さもちゃんと出ていて、表示もきちんと整っています。

jQuery.Deferreを使ってみる

目的は達成できたのでこれで終わりでも良いのですが、もし読み込むものを増やす場合、そのたびにcompleteを治さなければならないので面倒です。

そこでjQuery.Deferredを使って、xmlが2つとも読み込まれたらheightLineを実行する非同期処理にしてみます。

$(function(){

    var func01 =
        $.ajax({
            url: "xml01.xml",
            async: true,
            cache: false,
            dataType:"xml",
            success: function(xml){
                $(xml).find('text').each(function(){
                    var text = $(this).text();
                    $('.txt01').append('<p>' + text + '</p>');
                });
            }
        });

    var func02 =
        $.ajax({
            url: "xml02.xml",
            async: true,
            cache: false,
            dataType:"xml",
            success: function(xml){
                $(xml).find('text').each(function(){
                    var text = $(this).text();
                    $('.txt02').append('<p>' + text + '</p>');
                });
            }
        });

    $.when(func01, func02).done(function() {
        $(".bg > div").heightLine();
        var txt01Height = $('.txt01').height();
        var txt02Height = $('.txt02').height();
        $('.height01').append('1つめの高さ ' + txt01Height + 'px');
        $('.height02').append('2つめの高さ ' + txt02Height + 'px');
    });

});

こうすることで、$.whenに中にある処理をfunc01とfunc02が終わったあとに実行してくれます。便利ですね。

参考ページ