Javascript 为什么canvas.toBlob和canvas.toDataURL有不同的返回类型

Javascript 为什么canvas.toBlob和canvas.toDataURL有不同的返回类型,javascript,html,html5-canvas,todataurl,Javascript,Html,Html5 Canvas,Todataurl,canvas.toBlob()需要回调函数,但canvas.toDataURL()会同步返回结果。为什么不同?这不是问题,但我非常好奇,我找不到解释为什么会这样。因为toDataURL是一个早期错误 在实现时(由SafariIIRC实现),FileAPI仍然只是在讨论中,导出画布的结果已经是一种需要。因此他们制作了这个方法,它以一个方便的数据URL返回数据,您可以直接使用它作为文档中几个元素的src。此时,同步返回它听起来是个好主意,CanvasAPI中的所有内容都是同步的 但几年后,随着越来越

canvas.toBlob()需要回调函数,但canvas.toDataURL()会同步返回结果。为什么不同?这不是问题,但我非常好奇,我找不到解释为什么会这样。

因为
toDataURL
是一个早期错误

在实现时(由SafariIIRC实现),FileAPI仍然只是在讨论中,导出画布的结果已经是一种需要。因此他们制作了这个方法,它以一个方便的数据URL返回数据,您可以直接使用它作为文档中几个元素的
src
。此时,同步返回它听起来是个好主意,CanvasAPI中的所有内容都是同步的

但几年后,随着越来越多的实现、越来越多的使用和新的API,显然
toDataURL
不是一个好主意。就像同步XHR一样,如果您已经足够大,可以记住。
即使您可以以同步方式拥有数据URL,但显示它仍然是一项异步任务

要从画布生成图像文件是一个缓慢的操作,您需要导出所有像素数据,将其解乘,然后调用压缩算法

除此之外,数据URL需要存储为base64编码字符串,比它所表示的二进制数据大34%,并在每次分配给DOM中某个位置时复制到内存中

FileAPI引入了将二进制数据保存在内存中的方法,以及能够显示、操作或将其原样发送到服务器的方法。所有这些都意味着最小的内存开销=>数据URL已经过时(在大多数情况下)


因此,决定添加一个新方法,该方法将利用这些新API,并将返回一个Blob而不是一个数据URL。在针对UI阻塞操作的常见斗争中,已经确定此方法将是异步的(,但不幸的是,这是在Promise出现之前…)。现在所有需要同步完成的事情就是抓取像素数据,就像
getImageData
所做的那样。剩下的操作可以并行完成。

是的,这有点奇怪,可能就是事情的结局。(不过异步在这里很重要,因为它让浏览器在编码过程中不会阻塞UI。)canvas.toDataURL()比Blob()标准化之前要老得多。在此期间,人们意识到,node.js普及的异步接口将极大地提高高分辨率图像和移动性能,从而使主机环境在调度处理和处理RAM时具有更大的灵活性,而不会停止或减慢页面的执行。实际上所有的Blob()接口都是异步的。@dandavis你能把它作为一个答案发布出来,这样我就可以对它进行升级吗?我觉得你的答案很好,如果你能给我一个答案,别人会投你更高的票too@dandavis
几乎所有的Blob()接口都是异步的
除了Blob构造函数和任何Blob方法之外?@kaido:是的,使用Blob的接口都是异步的:FileReader、Fetch等等……这些都很好,除非您遇到浏览器有意设置的其他限制,例如触发下载必须从用户单击事件同步进行。例如,如果在混合中抛出一个类似toBlob的异步调用,Safari就会阻止您。这是一个好主意,直到它突然不是。@user2867288他们需要在哪个平台上下载才能成为用户手势的一部分?在macOs上,它们显然允许从DOM中不存在的元素执行此操作。用户的手势应该持续几毫秒,不管怎样,你的画布真的有那么大吗?需要几毫秒才能导出?iOS。这不是它需要多长时间,而是它是异步的,即使它需要1毫秒,你也会失去点击事件的信任。这是出乎意料的。。。根据规格,应该有一个,即使他们没有定义一个下限,最后我检查了所有UAs同意至少几个毫秒。在你的评论中,“你的画布真的有那么大吗?它需要几毫秒才能导出”,即使是4k画布也需要几秒钟,而不是几毫秒才能在中型笔记本电脑上转换成blob。规范不应在任意的时间范围内编写。