我想从函数
之外的回调中访问变量值function test()
{
var videoData=[];
searchYTVideos("test1",0,function(vidYT){
//concat to videoData
videoData = videoData.concat(vidYT);
});
searchVideo("test2",0,function(vidDM){
//concat to videoData
videoData = videoData.concat(vidDM);
});
console.log(videoData);
}
但是,我得到一个空白值。如何将vidYT和vidDM的值连接到videoData
答案 0 :(得分:0)
当浏览器点击console.log
时,假设两个搜索功能都是异步的,那么videoData
可能仍然为空,因为回调尚未执行。
欢迎来到JS的异步奇迹!
通过异步,你不能只做return
数据,因此回调。
你可以做的是为你的搜索功能调用第三个函数,它检查两个回调是否都被执行。或者在另一个中嵌入一个电话。然后,您可以安全地console.log
videoData
{{1}}。这意味着将代码从通常的同步模式中分离出来。
答案 1 :(得分:0)
代码是异步的,因此console.log
在调用回调之前正在执行。
您可以尝试嵌套回调:
var videoData=[];
searchYTVideos("test1", 0, function(vidYT) {
//concat to videoData
videoData = videoData.concat(vidYT);
searchVideo("test2", 0, function(vidDM){
//concat to videoData
videoData = videoData.concat(vidDM);
console.log(videoData);
});
});
或者如果您不想嵌套它们,可以使用flags / counter和第三个函数来检查是否已调用回调:
var videoData=[];
var numCalled = 0;
searchYTVideos("test1",0,function(vidYT){
//concat to videoData
videoData = videoData.concat(vidYT);
numCalled++;
logData();
});
searchVideo("test2",0,function(vidDM){
//concat to videoData
videoData = videoData.concat(vidDM);
numCalled++;
logData();
});
function logData() {
if(numCalled === 2) {
console.log(videoData);
}
}
就个人而言,我认为嵌套版本更容易理解。
答案 2 :(得分:0)
我怀疑问题不是范围(你的范围没有问题),而是同步。 searchYTVideos
和searchVideo
都进行回调这一事实向我表明他们是asynchronous
;也就是说,当JavaScript引擎有时间时,它们会工作,然后然后调用回调。如果您可以指定虚构的“步骤编号”,它可能看起来像这样:
1 var videoData=[];
2 searchYTVideos("test1",0,function(vidYT){
//concat to videoData
15 videoData = videoData.concat(vidYT);
});
3 searchVideo("test2",0,function(vidDM){
//concat to videoData
23 videoData = videoData.concat(vidDM);
});
4 console.log(videoData);
// other stuff happens for a while...
请注意,在这个虚构的示例中,我先searchYTVideos
完成,但没有任何内容表明它不是另一种方式:searchVideo
首先完成,然后searchYTVideos
完成了。
要解决此问题,您可以像其他人建议的那样链接这些功能,或者您可以使用承诺:
<!-- "Q" promises library -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/q.js/1.0.0/q.js"></script>
<script>
var videoData=[];
var deferred1 = Q.defer();
searchYTVideos("test1",0,function(vidYT){
//concat to videoData
videoData = videoData.concat(vidYT);
deferred1.resolve();
});
var deferred2 = Q.defer();
searchVideo("test2",0,function(vidDM){
//concat to videoData
videoData = videoData.concat(vidDM);
deferred2.resolve();
});
Q.all([deferred1.promise, deferred2.promise]).then(function(){
console.log(videoData);
});
</script>
答案 3 :(得分:0)
您可以使用promise来解决此问题。来自documentation:
Promise接口不一定代表值的代理 在创作时就知道了。它允许您将处理程序关联到 异步操作最终成功或失败。这让我们 异步方法返回类似于同步方法的值:相反 对于最终值,异步方法返回一个promise 在将来的某个时刻有价值。
阅读 this 并开始工作。我们将使用jquery when 函数。
$.when(searchYTVideos("test1",0), searchVideo("test2", 0)).done(function(data){
// your logic
});
我的代码只是示例,在您的情况下,promise方法非常强大且有用。它有助于避免spaggeti代码。
还有非常good explanation的例子