close

原文網址:http://blog.yam.com/tagtoo/article/30242304

以下原文轉載

------------------------------------------------------------------------------------------------------------

最近試著把Tagtoo的服務中  利用到facebook api的部分改成新版的api
 由於當初第一次寫的時候有step by step的tutorial  而那篇tutorial裡面講到的功能  差不多就是我要的
 所以不費太多心思就把它完成了  現在新版api似乎還找不到那麼詳細的教學
 便花了一些時間摸索  這裡是一些心得  備忘之餘  若能幫其他開發者省一點時間
 也是功德一件摟~

Note: 我用的純粹是 javascript SDK

 先來講一個很容易發生的錯誤

1 var uid;
2 var email;
3 var name;
4 alert("outside: " + email); 
5 FB.api('/me', function(response) {
6     uid = response.uid;
7     email = response.email;
8     name = response.name;
9     alert("inside: " + email);
10 });
11 alert("outside: " + email);

以上的code做的事很簡單-- 取得用facebook connect登入你網站的網友之email
我們將會以facebook api進行查詢(第5~10行) 然後用變數"email"來存這個查詢到的值
注意第4 9 和 11行都是單純的alert指令 目的只是方便觀察變數email的值
不算是實質內容的一部分

實際執行上述程式碼 會發現一個很奇怪的現象
總共出現三次對話視窗  內容分別是 
1st: outside: undefined(第4行的執行結果)
2nd: outside: undefinde(第11行的執行結果)
3rd: zouber@gmail.com(第9行的執行結果)
若是沒經驗的話  一定會覺得很奇怪 
我明明在第7行已經賦與email值了 怎麼還是undefined?

仔細一想 合理的解釋 應該是第11行優先於第7行執行了
按理說程式運行原則上是由上至下逐行執行才對 怎麼會這樣?

可以先動動腦...



動動腦時間










問題出在第5行  當我們用facebook api查詢網友資料時
其實就隱含了ajax的意涵在裏頭  我們實際上是對facebook的server發了一個ajax request
也因為如此  所以這類的facebook api都少不了指定一個callback function
亦即當這個請求完成時  原頁面必須要有對應的後續處理
所以  看起來輕輕鬆鬆的一行程式碼  其實已經隱含了複雜的ajax request發出程序在裏頭

相信對ajax稍有概念的人就知道  ajax其實就是為了達成媲美桌面應用程式的反應性產生的技術
達成的方式是當使用者發出此類的請求後  用非同步的方式去處理它
簡單來說就是發出請求後  原網頁繼續運行  完全不會有任何停滯
同時請求傳到伺服器   同步處理  直到處理完畢  用戶端收到通知
啟動callback function 處理伺服器回傳的資料(也可能沒有任何回傳資料)

一個有點類似的概念是飛彈的"射後不理"
戰機射出飛彈後  完全不必理它  此時戰機和飛彈各做各的事
像兩個不相干的個體  一段時間後戰機會收到通知以了解飛彈的去向
最終戰機會收到通知  便可知道飛彈到底是擊中目標還是失誤

所以本來是一直線的程式執行流程
到了第5行以後分岔成兩支
一支是程式原本的流程A
另一支是新啟動的  對facebook資料庫進行查詢的流程B兩個流程同步進行  流程B進行完畢後  才會執行第6~9行
而流程A直接就執行接下來的第11行 
所以  第7行和第11行之間變成沒有絕對的順序關係
而以現階段的網路速度來說  有非常大的機率是第11行比第7行(必須等遠端請求完成)還要先被執行
也就是我們所看到的實驗結果

這個bug道理其實不難  只是簡短一兩行facebook api就能進行ajax機制時
我們必須時時注意  別被下意識的直覺騙了
debug很累的...

Note: 若對本範例涉及的api有興趣  請見此頁 和 此頁
要取得網友的email 必須在他登入facebook connect 時請求權限
FBML語法: "<fb:login-button  perms='email, publish_stream'></fb:login-button>"
其中perms屬性即列舉所有想請求的權限  就本例而言
我請求了取得網友email以及發布訊息到他塗鴉牆(publish_stream)的權限

zouber

arrow
arrow
    全站熱搜

    yoonow 發表在 痞客邦 留言(0) 人氣()