2011-07-18 7 views
1

FacebookのグラフAPIを使用して、ユーザーのフレンドリストを取得し、テンプレートとランダムな友だちに基づいてステータスメッセージを生成しています。 return(response);の代わりにalert(response.data[0].name);を使用すると、私のコードが動作し、最初のFacebookの友人の名前がわかります。私のコードでそれをさらに使うと、定義されていないエラーが発生します。数時間かけて問題を解決しようとしていますが、これ以上のレスポンスやJSONフォーマットの問題を使用できないスコープに関する問題があると思います。私はjQueryのJSON解析も試してみましたが、そこには何も追加できませんでした。JSON出力はコード内で未定義のままですが、アラートは問題ありませんが、これはスコープに問題がありますか?

shuffle = function(v){ 
    for(var j, x, i = v.length; i; j = parseInt(Math.random() * i), x = v[--i], v[i] = v[j], v[j] = x); 
    return v; 
}; 

function getFriends() { 
    FB.login(function(response) { 
     if (response.session && response.perms) { 
     FB.api('/me/friends', function(response) { 
      return response; 
     }); 
     } 
    } , {perms:'publish_stream'}); 
}; 

function selectFriend(){ 
    var friends = getFriends(); 
    friends = friends.data[0]; 
    var findex = friends.length 
    var randomNumber = (Math.floor(Math.random() * 10) % findex); 
    return(friends[randomNumber].name); 
}; 

function process(status){ 
    status = status[0].toString(); 
    var cindex = status.indexOf("{{friend}}"); 

    while (cindex != -1){ 
     status = status.replace("{{friend}}",selectFriend()); 
     cindex = status.indexOf("{{friend}}"); 
    } 
    return(status); 
}; 

function newStatus(){ 
    var status = [ 
     "This status is named {{friend}}", 
     "This status loves {{friend}} but likes {{friend}} too.", 
     "This status goes by {{friend}} but you can call it {{friend}} if you like.", 
     "This status hates {{friend}}" 
    ]; 

    status = shuffle(status); 
    $('#status').text(process(status)); 
} 

コードは、クリック時にnewStatus()を呼び出すことから始まります。

EDIT:

shuffle = function(v){ 
    for(var j, x, i = v.length; i; j = parseInt(Math.random() * i), x = v[--i], v[i] = v[j], v[j] = x); 
    return v; 
}; 

function newStatus(){ 
    var status = [ 
     "This status is named {{friend}}", 
     "This status loves {{friend}} but likes {{friend}} too.", 
     "This status goes by {{friend}} but you can call it {{friend}} if you like.", 
     "This status hates {{friend}}" 
    ]; 
    status = shuffle(status); 
    status = status[0].toString(); 

    FB.login(function(response) { 
     if (response.session && response.perms) { 
     FB.api('/me/friends', function(response) { 
      var friends = response.data; 
      var findex = friends.length 

      var cindex = status.indexOf("{{friend}}"); 

      while (cindex != -1){ 
       var randomNumber = (Math.floor(Math.random() * 10) % findex); 
       var name = friends[randomNumber].name; 

       status = status.replace("{{friend}}",name); 
       cindex = status.indexOf("{{friend}}"); 
      } 
      $('#status').text(status); 
     }); 
     } 
    } , {perms:'publish_stream'}); 
} 

答えて

2

問題はFBのAPIへの呼び出しは非同期であることをおそらくです:ここで私はjfriend00の答えの後に動作するように私のコードをリファクタリングする方法です。つまり、FB.api()を呼び出すと、FBへのajax呼び出しが開始されます。そのajax呼び出しが完了している間、あなたの他のコードは引き続き実行されます。実際、getFriendsの呼び出しは終了し、selectFriend()の残りの部分はFB ajax呼び出しが完了する前に実行されます。

次に、FB APIコールが完了すると、完了関数が呼び出されます(おそらくアラートを送信した場所)。あなたのコードでは、あなたは完成関数で意味のある何もしていません。応答を返すだけです

return response; 

しかし、これは何も役に立ちません。その戻り値はgetFriends()関数からの戻り値ではありません。これは、AJAXエンジンの中の何かへの戻りです。

FB.api(の応答で有用なことを行う場合は、そのコードを実行するか、FB.api()呼び出しで指定された完了関数からそのコードを呼び出す必要があります。

あなたは、この擬似コードのような何かをしなければならないでしょう:

function getFriends() { 
    FB.login(function(response) { 
     if (response.session && response.perms) { 
     FB.api('/me/friends', function(response) { 
      var friends = response.data[0]; 
      var findex = friends.length 
      var randomNumber = (Math.floor(Math.random() * 10) % findex); 
      var name = friends[randomNumber].name; 
      // now continue on with whatever you want to do with the random friend info 
      // you cannot just return data from this callback, you have to actually carry 
      // out whatever you were going to do with the data here 
     }); 
     } 
    } , {perms:'publish_stream'}); 
}; 

function selectFriend(){ 
    getFriends(); 
    // the getFriends() function is asynchronous and the FB.api() call has not yet 
    // completed so we can't do anything here yet as we have to wait for the 
    // FB.api() call to finish first. 
}; 
+0

まず、あなたの時間のおかげで、私はそれを感謝しています。私は、データが準備される前に次の機能が呼び出されるため、タイミングに関して、そしてなぜそれがコールの外で失敗しているのかを見ています。基本的にロジックをAPI呼び出し内に移動することをお勧めしたら、意図した結果に達すると思われますが、API呼び出しから戻すという問題が残っています。私はランダムな友人の名前(呼び出しの目的)を思いつくことができますが、それはまだ置換ループ内で使用するには速すぎます。 –

+0

論理的には、あなたがしなければならないことは、FB呼び出しを行い、あなたの他の作業をまだ行わないことです。 FB呼び出しが完了し、FBデータを取得すると、FB呼び出しが完了して関数が呼び出されます。これはFBデータがあるため、他のすべての作業を行います。ループの途中でAPI呼び出しを行うことはできず、結果をループ内で使用できることが期待されます。これは非同期プログラミングです。時には痛みですが、それはブラウザの作業でAjaxが呼び出す方法です。 – jfriend00

+0

いいえ、私はこの答えを完了してマークしました。私は今、必要なものに応じて、すべての関数をリファクタリングして、非同期の前または非同期で実行するようにしています。上記のコードを上に投稿しているので、似たような問題を抱えている人なら誰でもあなたの助けを借りてうまくいくでしょう。 –

関連する問題