2013-01-31 105 views
3

我有jQuery的問題。函數中的jQuery變量範圍

我想獲得img的真實寬度/高度。現在
我用這個函數來得到它:

var imageSize = function(image) { 
    var realImageSize = { }; 

    $("<img/>") // Make in memory copy of image to avoid css issues 
    .attr("src", $(image).attr("src")) 
    .load(function() { 
     realImageSize.width = this.width; // Note: $(this).width() will not 
     realImageSize.height = this.height; // work for in memory images. 

     alert(realImageSize['height']); // Valid height 
    }); 

    alert(realImageSize['height']); // Undefined 

    return realImageSize; 
} 

所以我在存儲器複製的圖像,然後我獲取和設置圖像的.load方法的實際尺寸。

現在,問題在於var realImageSize變量由於某種原因在此範圍內不可用。誰能告訴我爲什麼?

+0

'load()'是異步的,因此在調用回調之前已經退出。你試圖做的是不可能的。你需要在回調中處理所有依賴於load()的邏輯。 –

+1

這是類似的(也許是重複的,也許不是)這個問題:http://stackoverflow.com/questions/12475269/variable-doesnt-get-returned-from-ajax-function –

回答

6

這不是範圍問題,它很好,但同步性問題:您正在執行加載回調之前讀取值。

您給出的作爲參數load的回調不會立即執行,而只會在圖像加載完成後才執行。

通常的解決辦法是沒有返回值,但提供的回調:

var fetchImageSize = function(image, callback) { 
    $("<img/>") // Make in memory copy of image to avoid css issues 
    .load(function() { 
     var realImageSize = { }; 
     realImageSize.width = this.width; // Note: $(this).width() will not 
     realImageSize.height = this.height; // work for in memory images. 
     callback(realImageSize); 
    }).attr("src", image.src); 
}; 

fetchImageSize(myImage, function(realImageSize){ 
    alert(realImageSize['height']); // NOT Undefined 
}); 

請注意,你應該總是設置src 後您設置的onload回調。某些瀏覽器(如果緩存中有圖像),如果在設置源後設置,則可能不會調用onload回調。

+0

謝謝!我不知道。有沒有辦法'等待'直到'.load'完成? – NSAddict

+0

否:您必須在回調或回調中調用的函數中執行代碼。 –

+1

@NSAddict no。但是,您可以將回調作爲參數,也可以返回承諾。 –

2

你的第二個警報被稱爲前負載的功能是completed.use回調...

試試這個

var imageSize = function(image,callback) { 
    var realImageSize = { }; 

    $("<img/>") // Make in memory copy of image to avoid css issues 
    .attr("src", $(image).attr("src")) 
    .load(function() { 
    realImageSize.width = this.width; // Note: $(this).width() will not 
    realImageSize.height = this.height; // work for in memory images. 

    alert(realImageSize['height']); // Valid height 
    callback(realImageSize); 
    }); 


} 

imageSize(img, function(realImageSize) { 
    alert(realImageSize.height); 
}); 
+0

謝謝!不幸的是,這不會起作用,因爲樣式'width'可以應用於img。 – NSAddict

+0

更新..:)... – bipen

2

使用回調。其他答案解釋異步的東西,我不會重複:-)

var imageSize = function(image, callback) { 
. 
. 
. 
    .load(function() { 
     realImageSize.width = this.width; // Note: $(this).width() will not 
     realImageSize.height = this.height; // work for in memory images. 

     callback(realImageSize); 
    }); 

然後,你可以這樣調用該函數:

imageSize(img, function(size) { 
    alert(size.height); 
}); 
2

這是Javascript程序員的一個常見問題誰來自其他語言。 Javascript使用稱爲異步調用的執行模型。簡而言之,當你註冊的​​事件的功能,執行將功能將被當圖像已經加載推遲到,而函數體(即第二alert())的其餘部分將立即執行:

var imageSize = function(image) { 
    //runs now 
    var realImageSize = { }; 

    //runs now 
    $("<img/>") // Make in memory copy of image to avoid css issues 
    .attr("src", $(image).attr("src")) 
    .load(function() { 
     //this code can run say 5 sec later 
     realImageSize.width = this.width; // Note: $(this).width() will not 
     realImageSize.height = this.height; // work for in memory images. 

     alert(realImageSize['height']); // Valid height 
    }); 

    //runs now. The realImageSize variable is yet to be created in 5 sec 
    alert(realImageSize['height']); // Undefined 

    //runs now 
    return realImageSize; 
} 

解決此類問題的常見模式是將回調傳遞給需要很長時間的函數。

//** Get an image URL and a callback function that will be called when the image is loaded and the size is detected 
function imageSize (src, callback) { 
    $("<img src="' + src + '"/>").load(function() { 
     //here we call the callback which will be called when the image is loaded 
     callback({ 
      width: this.width, 
      height: this.height 
     }); 
    }); 
} 

imageSize('my/image/path.png', function (imageSize) { 
    //this callback function will be called when the image is loaded 
    alert('width: ' + imageSize.width + ', height: ' + imageSize.height); 
});