Javascript 从具有嵌套ajax调用的函数返回对象
我想写一个javascript函数,返回来自youtube视频的信息;更具体地说,我想在json对象中获取通过搜索获得的ID和视频长度。因此,我查看了youtube API,并提出了以下解决方案:Javascript 从具有嵌套ajax调用的函数返回对象,javascript,jquery,ajax,jquery-deferred,Javascript,Jquery,Ajax,Jquery Deferred,我想写一个javascript函数,返回来自youtube视频的信息;更具体地说,我想在json对象中获取通过搜索获得的ID和视频长度。因此,我查看了youtube API,并提出了以下解决方案: function getYoutubeDurationMap( query ){ var youtubeSearchReq = "https://gdata.youtube.com/feeds/api/videos?q="+ query + "&a
function getYoutubeDurationMap( query ){
var youtubeSearchReq = "https://gdata.youtube.com/feeds/api/videos?q="+ query +
"&max-results=20&duration=long&category=film&alt=json&v=2";
var youtubeMap = [];
$.getJSON(youtubeSearchReq, function(youtubeResult){
var youtubeVideoDetailReq = "https://gdata.youtube.com/feeds/api/videos/";
for(var i =0;i<youtubeResult.feed.entry.length;i++){
var youtubeVideoId = youtubeResult.feed.entry[i].id.$t.substring(27);
$.getJSON(youtubeVideoDetailReq + youtubeVideoId + "?alt=json&v=2",function(videoDetails){
youtubeMap.push({id: videoDetails.entry.id.$t.substring(27),runtime: videoDetails.entry.media$group.media$content[0].duration});
});
}
});
return youtubeMap;
}
函数GetYouTube教育地图(查询){
变量youtubeSearchReq=”https://gdata.youtube.com/feeds/api/videos?q=“+查询+
“&max results=20&duration=long&category=film&alt=json&v=2”;
var youtubeMap=[];
$.getJSON(youtubeSearchReq,函数(youtubeResult){
变量youtubeVideoDetailReq=”https://gdata.youtube.com/feeds/api/videos/";
对于(var i=0;iYes),应该使用延迟对象
这里最简单的方法是创建一个数组,您可以在其中存储内部$.getJSON()
调用的jqXHR
结果
var def = [];
for (var i = 0; ...) {
def[i] = $.getJSON(...).done(function(videoDetails) {
... // extract and store in youtubeMap
});
}
然后在整个函数的末尾,使用$。当
创建一个新的承诺时,该承诺将仅在所有内部调用完成后才能解决:
return $.when.apply($, def).then(function() {
return youtubeMap;
});
然后使用.done
处理函数的结果:
getYoutubeDurationMap(query).done(function(map) {
// map contains your results
});
有关使用此YouTube API的演示,请参阅。该演示演示了延迟对象如何允许您将AJAX调用与“持续时间搜索”的后续数据处理完全分离
代码有点长,但在这里也可以复制。然而,虽然代码比您预期的要长,但请注意,这里的通用函数现在可用于您可能希望对YouTube API进行的任何调用
// generic search - some of the fields could be parameterised
function youtubeSearch(query) {
var url = 'https://gdata.youtube.com/feeds/api/videos';
return $.getJSON(url, {
q: query,
'max-results': 20,
duration: 'long', category: 'film', // parameters?
alt: 'json', v: 2
});
}
// get details for one YouTube vid
function youtubeDetails(id) {
var url = 'https://gdata.youtube.com/feeds/api/videos/' + id;
return $.getJSON(url, {
alt: 'json', v: 2
});
}
// get the details for *all* the vids returned by a search
function youtubeResultDetails(result) {
var details = [];
var def = result.feed.entry.map(function(entry, i) {
var id = entry.id.$t.substring(27);
return youtubeDetails(id).done(function(data) {
details[i] = data;
});
});
return $.when.apply($, def).then(function() {
return details;
});
}
// use deferred composition to do a search and then get all details
function youtubeSearchDetails(query) {
return youtubeSearch(query).then(youtubeResultDetails);
}
// this code (and _only_ this code) specific to your requirement to
// return an array of {id, duration}
function youtubeDetailsToDurationMap(details) {
return details.map(function(detail) {
return {
id: detail.entry.id.$t.substring(27),
duration: detail.entry.media$group.media$content[0].duration
}
});
}
// and calling it all together
youtubeSearchDetails("after earth").then(youtubeDetailsToDurationMap).done(function(map) {
// use map[i].id and .duration
});
是的,您应该使用延迟对象
这里最简单的方法是创建一个数组,您可以在其中存储内部$.getJSON()
调用的jqXHR
结果
var def = [];
for (var i = 0; ...) {
def[i] = $.getJSON(...).done(function(videoDetails) {
... // extract and store in youtubeMap
});
}
然后在整个函数的末尾,使用$。当
创建一个新的承诺时,该承诺将仅在所有内部调用完成后才能解决:
return $.when.apply($, def).then(function() {
return youtubeMap;
});
然后使用.done
处理函数的结果:
getYoutubeDurationMap(query).done(function(map) {
// map contains your results
});
有关使用此YouTube API的演示,请参阅。该演示演示了延迟对象如何允许您将AJAX调用与“持续时间搜索”的后续数据处理完全分离
代码有点长,但在这里也可以复制。然而,虽然代码比您预期的要长,但请注意,这里的通用函数现在可用于您可能希望对YouTube API进行的任何调用
// generic search - some of the fields could be parameterised
function youtubeSearch(query) {
var url = 'https://gdata.youtube.com/feeds/api/videos';
return $.getJSON(url, {
q: query,
'max-results': 20,
duration: 'long', category: 'film', // parameters?
alt: 'json', v: 2
});
}
// get details for one YouTube vid
function youtubeDetails(id) {
var url = 'https://gdata.youtube.com/feeds/api/videos/' + id;
return $.getJSON(url, {
alt: 'json', v: 2
});
}
// get the details for *all* the vids returned by a search
function youtubeResultDetails(result) {
var details = [];
var def = result.feed.entry.map(function(entry, i) {
var id = entry.id.$t.substring(27);
return youtubeDetails(id).done(function(data) {
details[i] = data;
});
});
return $.when.apply($, def).then(function() {
return details;
});
}
// use deferred composition to do a search and then get all details
function youtubeSearchDetails(query) {
return youtubeSearch(query).then(youtubeResultDetails);
}
// this code (and _only_ this code) specific to your requirement to
// return an array of {id, duration}
function youtubeDetailsToDurationMap(details) {
return details.map(function(detail) {
return {
id: detail.entry.id.$t.substring(27),
duration: detail.entry.media$group.media$content[0].duration
}
});
}
// and calling it all together
youtubeSearchDetails("after earth").then(youtubeDetailsToDurationMap).done(function(map) {
// use map[i].id and .duration
});
正如您所发现的,您不能直接返回youtubeMap
,因为它在返回点还没有填充。但是您可以返回一个完全填充的youtubeMap
,可以使用例如.done()、.fail()
或.then()
执行
调用GetYouTubeEducationMap()
的形式如下:
getYoutubeDurationMap("....").done(function(query, map) {
alert("Query: " + query + "\nYouTube videos found: " + map.length);
});
注:
- 实际上,您可能会在
map
中循环,并显示.id
和.runtime
数据
- 顺序查询比并行查询更好,因为顺序查询对客户端和服务器都更友好,而且更可能成功
- 另一种有效的方法是返回一组单独的承诺(每个视频一个),并在完成时使用
$.when.apply(..)
,但是提取所需的数据会比较困难
正如您所发现的,您不能直接返回youtubeMap
,因为它在返回点尚未填充。但是您可以返回一个完全填充的youtubeMap
的承诺,可以使用例如.done()、.fail()
或.then()
来执行
调用GetYouTubeEducationMap()
的形式如下:
getYoutubeDurationMap("....").done(function(query, map) {
alert("Query: " + query + "\nYouTube videos found: " + map.length);
});
注:
- 实际上,您可能会在
map
中循环,并显示.id
和.runtime
数据
- 顺序查询比并行查询更好,因为顺序查询对客户端和服务器都更友好,而且更可能成功
- 另一种有效的方法是返回一组单独的承诺(每个视频一个),并在完成时使用
$.when.apply(..)
,但是提取所需的数据会比较困难
不,你应该提出一个同步请求。但不要这样做:学会使用Javascript的异步逻辑,你也可以做很多其他事情。在回调时执行事情……是的,你应该使用延迟对象。更多背景信息:不,你应该提出一个同步请求。但不要这样做:学会使用asynchronous的Javascript逻辑,你也可以处理很多其他事情。在回调时执行事情…是的,你应该使用延迟对象。更多背景信息:不错,但根据我的经验,串联运行查询会使批处理速度变慢,浏览器应该将并发AJAX查询的数量限制在4个左右如果它们是并行运行的。是的,它会运行得更慢,但更能保证完成。在这方面,我还没有对浏览器行为做过全面的回顾,但我不会对所有浏览器都施加保护。记住,现在有很多流行的“还rans”,特别是在Linux领域(包括Raspberry PI)-Midori、Dillo、Chromium、NetSurf、IceWeasel……它们的行为如何?我不知道。不错,但根据我的经验,以串联方式运行查询会使批处理速度变慢,如果并行运行,浏览器应该将并发AJAX查询的数量限制在4个左右。是的,它会运行得更慢,但更能保证不会o完成。在这方面,我还没有对浏览器行为做过全面的评估,但我不会对所有的浏览器都施加保护。请记住,现在有很多流行的“还rans”,特别是在Linux领域(包括树莓PI)——Midori、Dillo、Chromium、NetSurf、IceWeasel。。。