如何等到异步回调完成后才能使用检索到的数据
How can I wait until Asynchronous callbacks are finished before using the data retrieved?
我正试图创建一个查看器,该查看器使用twitch.tv api检查一组twitch流媒体,然后发布哪些用户当前在线以及他们正在流媒体播放的内容。我在弄清楚如何使用异步性质的回调时遇到了一些严重的问题。
我想为数组中的每个twitch用户循环一次api调用。在他们全部返回后,我希望能够对他们进行排序,并按照特定标准的顺序列出他们。
经过大量的研究,我正试图利用承诺来做到这一点。不过我还是想不通。
我用过这样一个问题:如何等待一组异步回调函数?还有这个问题:如何从异步调用返回响应?作为指导方针,但显然我仍然错过了一些重要的东西。我已经发布了代码的相关部分。如果能为我所缺少的东西提供任何帮助/推动,我将不胜感激。
$(document).ready(function() {
var channels = ["freecodecamp", "storbeck", "terakilobyte", "habathcx","RobotCaleb","thomasballinger","noobs2ninjas","beohoff","ESL_SC2", "brunofin"];
var test = [];
function getData(){
var promises = [];
for (var i = 0; i < channels.length; i++) {
promises.push($.getJSON('https://api.twitch.tv/kraken/streams/'+channels[i]+'?callback=?', function(data) {}));
}
$.when.apply($, promises).then(function() {
// returned data is in arguments[0][0], arguments[1][0], ... arguments[9][0]
// you can process it here
for(var j=0; j<promises.length; j++){
//console.log(promises[j].responseJSON);
test.push(promises[j]);
}
}, function() {
// error occurred
conole.log("get data error");
});
}
getData();
console.log("do I have data?: ");
for(var j=0; j<test.length; j++){
console.log(test[j].responseJSON); //This is empty and where I need the data!
}
});
在代码中,调用getData()
,然后在下一行迭代test
数组。这发生在事件循环的同一过程中,因此您不会给您的承诺任何机会来实际运行其逻辑并解决任何问题。逐行执行是同步的,在这两者之间不能执行任何操作。
解决方案是从getData
函数返回一个promise,然后等待它得到解决。
由于您使用Promises,因此也不需要对$getJSON
函数进行任何回调。
$(document).ready(function() {
var channels = [
"freecodecamp", "storbeck", "terakilobyte", "habathcx",
"RobotCaleb", "thomasballinger", "noobs2ninjas", "beohoff",
"ESL_SC2", "brunofin"
];
var test = [];
function getData() {
var promises = [];
for (var i = 0; i < channels.length; i++) {
promises.push(
$.getJSON(
'https://api.twitch.tv/kraken/streams/'+channels[i]+'?callback=?'
)
);
}
return $.when.apply($, promises).then(function() {
for(var j=0; j<promises.length; j++){
test.push(promises[j]);
}
});
}
getData().then(function() {
console.log("do I have data?: ");
for(var j=0; j<test.length; j++) {
console.log(test[j].responseJSON);
}
});
});
我还建议对这段代码进行重构。这是一个有趣的问题,也是JavaScript中常见的问题,我想用这个例子演示如何处理promise数组。
每个异步操作都是独立运行的,你的直觉是正确的:你需要一些额外的工具来把所有的结果放在一起。
使用promise时,此工具为Promise.all
。事实上,jQuery的$.when
是类似的,尽管我发现Promise.all
由于其输入和返回类型而更容易使用。它也是标准的JavaScript,在所有现代浏览器中都可以使用。
Promise.all
可以用于在多个单独的promise解析时运行一些逻辑。形式上,Promise.all
接受一组promise并返回一个promise,该promise在所有输入promise解析(或其中一个被拒绝)时解析。它解析为一组已解析的值,个人承诺将解析为这些值。
由于Promise.all
采用了一个数组,因此它与map
和filter
等数组方法配合得很好。
function getStreams(channels) {
// Transform an array of channel names into an array of Promises
// representing the asynchronous action of getting the info
// about each channel.
const promises = channels.map(
channel => $.getJSON(
'https://api.twitch.tv/kraken/streams/'+channel+'?callback=?'
)
);
// Return a new promise which will resolve when *all* channels
// have been queried.
return Promise.all(promises);
}
const channels = [
"freecodecamp", "storbeck", "terakilobyte", "habathcx",
"RobotCaleb", "thomasballinger", "noobs2ninjas", "beohoff",
"ESL_SC2", "brunofin"
];
getStreams(channels).then(
// infos is an array of resolved data about the channels
infos => infos.forEach(
info => console.log(info)
)
);
异步正是名称的含义。
您只能在when回调的第一个函数中访问该数据。因为在那之前,数据不存在于您的页面上。
- 如何在corona sdk中从CK编辑器中检索数据
- XML2JSON并检索数据
- 如何基于两个下拉选择从数据库中检索数据
- 在检索数据时是否可以停止图像加载请求
- 正在从JSON对象检索数据
- 只有当Angular从资源对象检索数据时,才选择选项元素
- 如何使用JavaScript从文本框中检索数据
- html表单,它有文本和表,现在我想在一个简单的文本文件中保存和检索数据,如何实现它
- 我想使用纯Javascript从MS Dynamics CRM Online 2015添加/检索数据
- Firebase-正在从推送项目中检索数据
- 为什么可以't我从Json文件中检索数据
- 从 tinymce 文本区域检索数据时出现问题
- 从 ajax 函数从数据库中检索数据值
- 检索数据表中的指定行
- 调用c#函数从传递javascript变量的javascript中检索数据
- 使用jqueryAjax和php脚本从mysql检索数据时遇到的问题
- JQuery:从URL检索数据
- SharePoint 2010 Rest API错误(未检索数据)
- JQuery检索数据,但如果退出,则获取默认值
- jQuery,用于检索数据的变量