Розглянемо наступний (крихкий) код JavaScript:
var img = new Image;
img.src = "data:image/png;base64,..."; // Assume valid data
// Danger(?) Attempting to use image immediately after setting src
console.log( img.width, img.height );
someCanvasContext.drawImage( img, 0, 0 );
// Danger(?) Setting onload after setting src
img.onload = function(){ console.log('I ran!'); };
Запитання
- Чи мають бути негайно правильні ширина та висота зображення?
- Чи повинен малюнок на полотні працювати негайно?
- Чи
onload
слід викликати зворотний виклик (встановлений після зміни src)?
Експериментальні тести
Я створив просту тестову сторінку з подібним кодом. У Safari мої перші тести, і, відкривши сторінку HTML локально ( file:///
URL) і завантаження з мого сервера, показав все працює: висота і ширина правильний, полотно лебідці, і в onload
теж пожежі.
У Firefox v3.6 (OS X) завантаження сторінки після запуску браузера показує, що висота / ширина неправильна відразу після налаштування, drawImage()
не вдається. (Однак onload
обробник спрацьовує.) Однак, завантажуючи сторінку ще раз, ширина / висота правильні відразу після налаштування та drawImage()
роботи. Здається, Firefox кешує вміст URL-адреси даних як зображення і надає його негайну доступність, коли використовується в тому ж сеансі.
У Chrome v8 (OS X) я бачу ті самі результати, що і у Firefox: зображення доступне не відразу, але потрібно деякий час для асинхронного `` завантаження '' з URL-адреси даних.
На додаток до експериментальних доказів того, які вищезазначені браузери працюють чи не працюють, я б дуже любив посилання на специфікації того, як це повинно поводитися. Поки що мій Google-fu не відповідав цій задачі.
Грати
в безпеці Для тих, хто не розуміє, чому вищезазначене може бути небезпечним, знайте, що для безпечності слід використовувати подібні зображення:
// First create/find the image
var img = new Image;
// Then, set the onload handler
img.onload = function(){
// Use the for-sure-loaded img here
};
// THEN, set the src
img.src = '...';
onload
перш ніж встановлюватиsrc
. Але якщо подія завантаження іноді спрацьовує в поточному сузір'ї, тоді встановлення URI "даних" справді є асинхронним - що мене здивує. Цікаво!