0

我想从函数外部的回调中访问变量值

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

4

4 回答 4

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

个人认为嵌套版本更容易理解。

于 2014-02-27T16:55:27.237 回答
0

你可以使用 promise 来解决这个问题。从文档

Promise 接口代表一个在创建时不一定知道的值的代理。它允许您将处理程序与异步操作的最终成功或失败相关联。这让异步方法可以像同步方法一样返回值:异步方法返回的不是最终值,而是在未来某个时间点拥有值的承诺。

阅读本文并开始工作。我们将函数时使用jquery。

$.when(searchYTVideos("test1",0),  searchVideo("test2", 0)).done(function(data){
  // your logic
});

我的代码只是示例,promise 方法在您的情况下非常强大和有用。它有助于避免意大利面条代码。

用例子也很好的解释

于 2014-02-27T16:59:24.587 回答
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完成。

为了解决这个问题,你可以像其他人建议的那样链接函数,或者你可以使用 Promise:

<!-- "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>
于 2014-02-27T16:58:22.683 回答
0

当浏览器点击 时console.log,假设两个搜索函数都是异步的,那么videoData可能仍然是空的,因为回调尚未执行。

欢迎来到 JS 的异步奇迹!

任何异步,你不能只做一个return数据,因此回调。

你可以做的是为你的两个搜索函数调用第三个函数,它检查两个回调是否都被执行了。或者将一个调用嵌套在另一个调用中。console.log然后,您可以安全地使用videoData. 这意味着将您的代码从通常的同步模式中打破。

于 2014-02-27T16:53:59.163 回答