提问:如何获取以下代码中的data?

function fn(callback){

    setTimeout(function (){
       var data = 'hello';
    },1000);
    
}

我们通常会想到以下两种方式(但是以下两种方法都获取不到异步操作的结果):

(1)直接在定时器中返回data

function fn(callback){
 
    setTimeout(function (){
       var data = 'hello';
       return data;
    },1000);

}
console.log(fn());  //undefined

结果是undefined,我们并没有拿到定时器函数里面的 data。为什么呢?

我们知道 setTimeout 是一个异步函数,它不进入主线程、而进入"任务队列",只有等主线程任务执行完毕,"任务队列"才开始通知主线程,请求执行任务,该任务才会进入主线程执行。

所以fn函数的执行顺序应该是:

  • 执行fn()的时候,发现异步函数 setTimeout,不会立即执行,而是将它放到任务队列中。
  • 由于没有直接给fn函数一个return 返回值,所以它的默认的是return undefined。console.log(fn())的结果是 undefined。所以我们并没能得到 setTimeout里面的data,因为此时根本还没有执行setTimeout函数里面的回调函数。
  • 主线程任务执行完毕, setTimeout 时间到了之后,主线程开始执行 setTimeout里面的回调函数,返回data。

(2)在函数fn中返回data

function fn(callback){
    
    var data = '';
    
    setTimeout(function (){
        var data = 'hello';

    },1000);

    return data;
}
console.log(fn());  // ''

运行结果为空,返回了一个空字符串。原因在于setTimeout中的回调函数还没有执行之前,fn就已经返回data了。

正确的解决方法:采用回调函数

在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A。我们就说函数A叫做回调函数。

js代码会至上而下一条线执行下去,但是有时候我们需要等到一个操作结束之后再进行下一个操作,这时候就需要用到回调函数。

//如果需要获取一个函数中异步操作的结果,则必须通过回调函数来获取

function fn(callback){
    //var callback = function(data){console.log(data);}
    setTimeout(function (){
       var data = 'hello';
        callback(data);
    },1000);
}

fn(function (data){
    console.log(data);
})

python execjs 如何获取异步js结果 js获取异步函数的返回值_主线程

以上代码的执行顺序是:

  • 进入 fn 函数体
  • 发现异步函数 setTimeout,将它放到任务队列中
  • 1s以后执行 setTimeout 回调函数
  • 在setTimeout 回调函数里执行callback(data)相当于立即执行:function (data){ console.log(data); }),输出data值