2017-04-03 65 views
3

我試圖在函數內部使用d3.json()返回給定藝術家ID的Spotify API(如5K4W6rqBFWDnAN6FQUkS6x),但我無法弄清楚如何有效地返回數據。該功能看起來像d3 - 無法從json請求中返回數據?

// Get artist's related artist's information 
function relatedArtists(id){ 
    var jsonPromise = new Promise(function(resolve, reject) { 
    // Async JSON request 
    d3.json('https://api.spotify.com/v1/artists/' + id + '/related-artists', function(error, data){ 
     if(error) reject(error); 
     resolve(data.artists); 
    }); 
    }); 

    jsonPromise.then(function(success) { 
    console.log(success); 
    //return(success) //doesn't work 
    }); 

    jsonPromise.catch(function(error){ 
    console.error(error); 
    }); 

} 

我試着創建函數內的一個變量,然後修改它

function relatedArtists(id){ 
    var testVar = 'hello'; 
    var jsonPromise = new Promise(...{ 
    // Async JSON request 
    d3.json(...) 
    }); 
    jsonPromise.then(function(success) { 
    testVar = success; 
    }); 
    return(testVar); 
} 

testVar仍然'hello',儘管我盡了最大努力。我已經做了一些關於範圍和承諾的閱讀,但是如果有一些我不瞭解的核心機制,我很樂意做更多的事情。謝謝閱讀!

回答

3

您可以返回Promise和使用relatedArtists功能,像這樣

function relatedArtists(id) { 
 
    return new Promise(function(resolve, reject) { 
 
    d3.json('https://api.spotify.com/v1/artists/' + id + '/related-artists', function(error, data) { 
 
     if (error) { 
 
     \t reject(error); 
 
     } else { 
 
     \t resolve(data.artists); 
 
     } 
 
    }); 
 
    }); 
 
} 
 

 

 
relatedArtists('5K4W6rqBFWDnAN6FQUkS6x') 
 
    .then(function (data) { 
 
    console.log(data); 
 
    }) 
 
    .catch(function (error) { 
 
    console.log(error); 
 
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

在這種情況下,你不能將值賦給testVar,因爲d3.json是異步方法,這意味着,代碼執行後可以完成d3.json

4

由於請求的異步性質,響應在您的調用代碼中永遠不可用。你可以使用Promises(正如亞歷山大T.和你一樣,在很多情況下是不錯的選擇!),但d3.queue也做得很好。在我的代碼片段中,您可以看到如何使用多個請求的結果運行代碼。

function buildRelatedArtistUri(id) { 
 
    return 'https://api.spotify.com/v1/artists/' + id + '/related-artists'; 
 
} 
 

 
d3.queue() 
 
    .defer(d3.json, buildRelatedArtistUri('5K4W6rqBFWDnAN6FQUkS6x')) 
 
    .await(function(error, data) { 
 
    // data and data.artists are available in this function‘s scope only 
 
    console.log(data.artists); 
 
    }); 
 

 
d3.queue() 
 
    .defer(d3.json, buildRelatedArtistUri('5K4W6rqBFWDnAN6FQUkS6x')) 
 
    .defer(d3.json, buildRelatedArtistUri('3nFkdlSjzX9mRTtwJOzDYB')) 
 
    .await(function(error, data1, data2) { 
 
    // this function will be called once both functions have finished 
 
    console.log(data1.artists, data2.artists); 
 
    });
<script src="https://d3js.org/d3.v4.min.js"></script>

+0

哦,這真是COOL-所以'd3.queue'是直到請求完成推遲行動的一種方式?這似乎很有用,謝謝! –

+0

是的,你可以推遲任何回調消耗的異步函數。最重要的是,你可以配置[concurrency](https://github.com/d3/d3-queue/blob/master/README.md#queue)並且執行任務[abortable](https://github.com/d3 /d3-queue/blob/master/README.md#queue_abort)... – undko