1

我有一段代碼,它使用facebook v1.0 API獲取我的朋友朋友列表。我如何使用Promises重構這個回調地獄?

FB.api(
    { 
    method: 'fql.query', 
    query: 'SELECT uid, name, is_app_user FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=me()) AND is_app_user=1' 
    }, 
    function (response) { // response contains a list of friends 
    response.forEach(function(element){ // so for each friend 
     FB.api(
     '/' + element.uid + '/friends', 
     function (response) { // get a list of THEIR friends 
      console.log(response); // and output them 
     } 
    ); 
    }); 
    } 
); 

我想重構此代碼使用JavaScript承諾和.then()語法,更具可讀性和可維護性。

爲了澄清,我不喜歡在另一個FB.api調用中撥打FB.api電話的想法。特別是如果我有多個這些,他們可以相當深入地嵌套。

我想使用承諾,但我需要能夠通過response從以前的FB.api調用。

我該怎麼做?

理想的情況下,它會是這個樣子:

FB.api(
    { 
    method: 'fql.query', 
    query: 'SELECT uid, name, is_app_user FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=me()) AND is_app_user=1' 
    }, 
    function(response){ 
    return response; 
    }) 
.then(function(friends){ 
    friends.forEach(function(element){ 
    FB.api(
     '/' + element.uid + '/friends', 
     function (response) { 
     console.log(response); 
     } 
    ); 
    }); 
}) 

回答

1

首先一個小工具功能,它用於promisisfy FB.api() ...

//jQuery 
function FB_api(options) { 
    return $.Deferred(function(dfrd) { 
     return FB.api(options, dfrd.resolve); 
    }).promise(); 
} 

//Bluebird 
function FB_api(options) { 
    return new Promise(function(resolve, reject) { 
     return FB.api(options, resolve); 
    }); 
} 

你可以同樣使用Q.jswhen.js ......。

現在,你可以寫......

FB_api({ 
    method: 'fql.query', 
    query: 'SELECT uid, name, is_app_user FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=me()) AND is_app_user=1' 
}).then(function(response) { // response contains a list of friends 
    response.forEach(function(element) { // so for each friend 
     FB_api('/' + element.uid + '/friends').then(function (response) { // get a list of THEIR friends 
      console.log(response); // and output them 
     }); 
    }); 
});