2013-04-24 28 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()