[js]callback関数を使ってみた

Pocket
[`evernote` not found]

僕は、元々マークアップから入った人間なので、あまりプログラム的な部分は強くないのですが、必要に迫られてjava script(特にjquery)を触るようになってきました。
初歩的な事しかできないのが現状なのですが、勉強のために、僕がつまづいた事をご紹介したいと思います。

callback関数
Aの処理を終わったあとにそのAに対してBの処理を実行させる事・・・・でいいのかな。僕の認識はそんな感じですが、違っていたらご指摘ください。

例えば、外部のRSS情報を読み込ませて、生成したhml要素に対して「日付で検索して特定の日付以前のものに色をつける」とか。
(あまり実務的な例ではありませんが)

java scriptは基本的に上から一行づつ実行していきますので、単純に考えると

$(document).ready(function(){
  $.jGFeed('http://www.matsuaz.com/4_1/rss.xml'+'?'+(new Date()).getTime(),
  function(feeds){
    if(!feeds){
   return false;
		}
   for(var i=0; i<feeds.entries.length; i++){
    var entry = feeds.entries&#91;i&#93;;
    var date = new Date(entry.publishedDate);
    var pday =date.getDate();//日
    var pmonth = date.getMonth() + 1;//月
    var pyear = date.getFullYear();//年
    var fullDate = pyear + "/" +pmonth + "/" + pday;		
    var feedsItem = &#91;{
     title:entry.title,
     link:entry.link,
     postDate: fullDate,
    }&#93;;
    template = Handlebars.compile( $('#template').html());
    $('#feed').append(template(feedsItem))
		
   }
    }, 10);
		
		//RSSの読み込み後に続けて記述する
   var date = new Date('2012/8/10 23:59:59');
   $('#feed li span').each(function(){
    var entryDate = new Date($(this).html());
    if(date > entryDate){
     $(this).css('color','red');
    }
   });	 
});

と書いてしまいがちです。実際に実行してみると、RSSは読み込まれていますが、上記赤字の部分の処理(2012/8/10以前のエントリーの日付を赤くする)が実行されていないはずです。

DEMO(失敗例)

これは、色を変えるという処理が実行される時に、「RSSの読み込み→HTMLの生成」が完了していないからです。実在しないオブジェクトに対して処理を行う事はできませんので、当然、色を変える事は不可能です。

それではどうすればいいか。

$(document).ready(function(){
  $.jGFeed('http://www.matsuaz.com/4_1/rss.xml'+'?'+(new Date()).getTime(),
  function(feeds){
    if(!feeds){
   return false;
		}
   for(var i=0; i<feeds.entries.length; i++){
    var entry = feeds.entries&#91;i&#93;;
    var date = new Date(entry.publishedDate);
    var pday =date.getDate();//日
    var pmonth = date.getMonth() + 1;//月
    var pyear = date.getFullYear();//年
    var fullDate = pyear + "/" +pmonth + "/" + pday;		
    var feedsItem = &#91;{
     title:entry.title,
     link:entry.link,
     postDate: fullDate,
    }&#93;;
    template = Handlebars.compile( $('#template').html());
						
    //callbakc関数をhtml要素の生成後に実行する
    if($('#feed').append(template(feedsItem))){
     myCallback();
    };
		
   }
    }, 10);
		
  //callback関数として定義
  function myCallback() {
   var date = new Date('2012/8/10 23:59:59');
   $('#feed li span').each(function(){
    var entryDate = new Date($(this).html());
    if(date > entryDate){
     $(this).css('color','red');
    }
   });
  }		
 
});

色を変える処理の部分をcallback関数にして、「RSSの読み込み→HTMLの生成」が完了した段階で読みこまれるようにしました。これで意図通りの結果が得られます。

DEMO(callback関数を利用)

ちなみに、バッドノウハウとして、色を変える処理を$(window).loadイベントで実行させることも可能ですが(というかそうしてました)。これは処理のタイミングを遅らせるための苦肉の策として考えたモノです。

$(document).ready(function(){
  $.jGFeed('http://www.matsuaz.com/4_1/rss.xml'+'?'+(new Date()).getTime(),
  function(feeds){
    if(!feeds){
   return false;
		}
   for(var i=0; i<feeds.entries.length; i++){
    var entry = feeds.entries&#91;i&#93;;
    var date = new Date(entry.publishedDate);
    var pday =date.getDate();//日
    var pmonth = date.getMonth() + 1;//月
    var pyear = date.getFullYear();//年
    var fullDate = pyear + "/" +pmonth + "/" + pday;		
    var feedsItem = &#91;{
     title:entry.title,
     link:entry.link,
     postDate: fullDate,
    }&#93;;
    template = Handlebars.compile( $('#template').html());							
   }
    }, 10);
});
//window loadイベントでページが完全に表示されてから実行する
$(window).load(function() {
  function myCallback() {
   var date = new Date('2012/8/10 23:59:59');
   $('#feed li span').each(function(){
    var entryDate = new Date($(this).html());
    if(date > entryDate){
     $(this).css('color','red');
    }
   });
  }		
});

DEMO(window loadイベント)

ちなみに$(document).readyはDOMが構築されたら実行されるのに対して、
$(window).loadはページが完全に表示されたら実行しますので、上記のような使い方の場合は、ほぼほぼ意図通りに実行されますが、処理内容によっては、うまく動かない場合もありますので、やはりcallback関数を利用して実行した方が無難ですね。

[追記]
1.DEMO(window loadイベント)のソースが間違っていましたので修正しました。
2.コールバックのデモですが、HTMLの生成部分自体がjGFeedというRSSを展開するコードのコールバックになっているので、文字の色を変えるコードはコールバックのコーバックという扱いになるのでは。とのご指摘を頂きました。調べましたところ、ご指摘の通りで、下記のようにわざわざコールバック関数にしなくても、意図した動きを再現できました。

$(document).ready(function(){
  $.jGFeed('http://www.matsuaz.com/4_1/rss.xml'+'?'+(new Date()).getTime(),
  function(feeds){
    if(!feeds){
   return false;
		}
   for(var i=0; i<feeds.entries.length; i++){
    var entry = feeds.entries&#91;i&#93;;
    var date = new Date(entry.publishedDate);
    var pday =date.getDate();//日
    var pmonth = date.getMonth() + 1;//月
    var pyear = date.getFullYear();//年
    var fullDate = pyear + "/" +pmonth + "/" + pday;		
    var feedsItem = &#91;{
     title:entry.title,
     link:entry.link,
     postDate: fullDate,
    }&#93;;
    template = Handlebars.compile( $('#template').html());
						
    //html要素の生成
    $('#feed').append(template(feedsItem))
   //文字の色を変える処理
   var date = new Date('2012/8/10 23:59:59');
   $('#feed li span').each(function(){
    var entryDate = new Date($(this).html());
    if(date > entryDate){
     $(this).css('color','red');
    }
   });
   }
    }, 10);
});

DEMO(jGFeedのコールバックとして処理する)

Follow me!

Pocket
[`evernote` not found]

コメントは受け付けていません。