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 
     }); 
    }); 
});