2013-04-24 29 views
0

我知道这可能是一个真正的noob问题,但我看不出有什么问题就在这里被返回变量pic_real_width.的jQuery/JavaScript中,变量的作用域问题

我相信这是一个范围内的事情,但除此之外,使它全球(不能这样做)我不确定我可以如何设置并返回它。

由于提前,

function get_real_width(img){ 
    var pic_real_width; 
    $("<img/>") // Make in memory copy of image to avoid css issues 
     .attr("src", $(img).attr("src")) 
     .load(function() { 
     pic_real_width = this.width; 
     console.log(pic_real_width); // returns a number 
     }); 
    console.log(pic_real_width); //returns undefined 
    return pic_real_width; 
} 
+5

查一查异步VS同步。 – 2013-04-24 16:52:16

+0

第二个'的console.log(pic_real_width)'是'.load之前运行()'函数是。把你的return语句放在加载函数的末尾。 – PlantTheIdea 2013-04-24 16:53:03

+1

异步任务是asyncronous! – jAndy 2013-04-24 16:53:06

回答

1

简而言之,您传递加载的函数是异步函数,而异步函数具有模式函数的不同上下文。

在这个例子中,一个解决方案不能被遇到(我现在找不到解决方案),但是,你可以重构你的代码来获得异步的“真正宽度”,只是传递其他的在传递给load()的函数内部调用这个回调函数。

的东西,如:

function get_real_width(img, callback){ 
    var pic_real_width; 
    $("<img/>") // Make in memory copy of image to avoid css issues 
    .attr("src", $(img).attr("src")) 
    .load(function() { 
     pic_real_width = this.width; 
     callback(img, pic_real_width); // Call the function with the number expected 
    }); 
} 

当它刚刚得到的宽度和它返回的功能。

但是,我知道,它不能在某些情况下使用。

祝你好运。

1

你的功能已经退出了.load调用完成之前,因此没有要返回的值。

'pic_real_width'是在加载的回调函数期间设置的,但同时,您的函数在等待.load完成时继续执行,因此在设置值之前退出。

0

.load被附加load事件处理的图像和事件可能获得非同步方式启动(也可能是同步的,如果浏览器缓存图像),至极意味着.load调用返回马上和处理程序将不会有当您达到return pic_real_width;时已执行。

但是,您可以利用$.Deferred以优雅的方式解决此问题。

function get_real_width(img){ 
    var def = $.Deferred(); 
    $("<img/>") 
     .load(function() { 
     def.resolve(this.width); 
     }) 
     .attr("src", $(img).attr("src")); 
    return def; 
} 

get_real_width().done(function (width) { 
    console.log(width); 
}); 

请注意,我重视处理程序的图像缓存和事件被同步开除设置源的情况下,之前。

0

在英语中,这就是get_real_width目前正在做:

  1. 创建一个名为pic_real_width的局部变量。
  2. 用复制的src属性创建新<img/>元件,和一旦元件<img/>被加载,然后运行内部函数。 “一次/一次”部分就是每个人都描述为异步的部分,因为您不知道或无法控制相对于其他代码发生这种情况的时间。
  3. 立即记录并返回pic_real_width

注意,一旦内部函数被调用,完成pic_real_width将只设置,但可能不会被时间get_real_width退出发生,所以pic_real_width会当您登录并返回它不确定的。

那么,你如何解决这个问题?

这就要看你是如何使用的get_real_width结果。如果,例如,您已创建从get_real_width结果的警告,就像这样:

alert(get_real_width(some_img)); 

然后,你可以代替修改功能,使该警报内部连接到.load功能发生:

function alert_real_width(img){ 
    $("<img/>") 
     .attr("src", $(img).attr("src")) 
     .load(function() { 
     var pic_real_width = this.width; 
     alert(pic_real_width); 
     }); 
} 

很显然,我怀疑你正在做的alert,但应该给你如何解决这个问题的想法。对于更一般的解决方案,您可以像其他用户所建议的那样使用回调。

0

返回的承诺只是“有点”好......

function get_real_width(img, callback) { 
    var dfd= $.Deferred(function (dfd) { 

     $("<img/>") 
      .attr("src", $(img).attr("src")) 
      .load(function() { 
       dfd.resolve(this.width); 
      }); 
    }); 

    return dfd.promise(); 
} 
0

默认情况下,ajax()请求是异步因此请求完成之前调用ajax()通常会返回。您可以改用回调函数。

function get_real_width(img, callback){ 
    var pic_real_width; 
    $("<img/>") // Make in memory copy of image to avoid css issues 
    .attr("src", $(img).attr("src")) 
    .load(function() { 
     pic_real_width = this.width; 
     callback(pic_real_width); // Call the function with the number expected 
    }); 
} 

get_real_width(img, function(returnedData){ //anonymous callback function   
    console.log(myVariable); 
    return returnedData; 
}); 

如果您绝对必须,您可以使用async: false inside the call to ajax()