将图像 src 设置为数据 URL 是否应该立即可用?
考虑以下(脆弱的)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 = '...';
Consider the following (fragile) JavaScript code:
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!'); };
The Question(s)
- Should the image width and height be correct immediately?
- Should the canvas draw work immediately?
- Should the
onload
callback (set after the src was changed) be invoked?
Experimental Tests
I created a simple test page with similar code. In Safari my first tests, both by opening the HTML page locally (file:///
url) and loading it from my server, showed everything working: the height and width is correct, the canvas draw works, and the onload
also fires.
In Firefox v3.6 (OS X), loading the page after launching the browser shows that the height/width is not correct immediately after setting, drawImage()
fails. (The onload
handler does fire, however.) Loading the page again, however, shows the width/height being correct immediately after setting, and drawImage()
working. It would appear that Firefox caches the contents of the data URL as an image and has it available immediately when used in the same session.
In Chrome v8 (OS X) I see the same results as in Firefox: the image is not available immediately, but takes some time to asynchronously 'load' from the data URL.
In addition to experimental proof of what browsers the above does or does not work, I'd really love links to specs on how this is supposed to behave. So far my Google-fu has not been up to the task.
Playing It Safe
For those who don't understand why the above might be dangerous, know that you should use images like this to be safe:
// 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 = '...';
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于还没有人找到关于其行为方式的任何规范,因此我们必须对其行为方式感到满意。以下是我的测试结果。
总之:
onload
事件。src
后设置onload
处理程序并期望它被调用。如果有人能找到讨论此问题的规范,我会很乐意接受他们的答案。
As no one has yet found any specifications about how this is supposed to behave, we will have to be satisfied with how it does behave. Following are the results of my tests.
In summary:
onload
event.onload
handler after setting thesrc
and expect it to be invoked.If anyone can find specs discussing this, I will happily accept their answer instead.
将控制权交还给浏览器渲染引擎后,测试在 FF 4b9 和 Chromium 8.0.552.237 中报告
true
。我修改了这些部分:更新:是的,我理解这个“答案”更像是一条评论,但只是想指出这一点。经过测试,我得到了可重现的结果:
setTimeout
,在两种浏览器中,我第一次打开页面时都会得到false
,只有在点击后才得到true
F5。显式清除缓存后,重新加载后都会再次显示false
。setTimeout
时,宽度/高度测试始终评估为true
。在这两种情况下,图像第一次不会显示,只有在重新加载页面后才会显示。
After giving control back to the browser's rendering engine, the test reports
true
in FF 4b9 and Chromium 8.0.552.237. I modified these parts:Update: Yes, I understand this 'answer' is more like a comment, but just wanted to point it out. And after testing I get reproducible results:
setTimeout
, in both browsers I getfalse
the first time I open the page andtrue
only after hitting F5. After explicitly clearing the cache both sayfalse
again after reloading.setTimeout
the width/height test always evualuates totrue
.In both cases the image doesn't show up the first time, only after reloading the page.