i有一个情况,用户将图像设置为URL或使用转换为blob对象URL的字节。我的理解是,为了防止资源泄漏,我应该在更改斑点对象时释放斑点对象的URL,但是我不确定是否正确检查了旧URL的类型。目前,我正在这样做的方法是检查URL是否以'blob:'
开头。这是一个玩具示例函数,证明它确实有效:
var url;
for (i = 0; i < 5; i++) {
var oldurl = url;
console.log('i = ' + i)
if (i == 0 || i == 2 || i == 3) {
console.log('Switching to Object URL')
url = URL.createObjectURL(new Blob(new Uint8Array(0),
{type: 'image/png'}));
} else {
console.log('Switching to URL')
url = 'https://example.com/example-image.png';
}
if (oldurl && oldurl.startsWith('blob:')) {
console.log('Freeing old object url')
URL.revokeObjectURL(oldurl);
}
}
这是正确的方法吗?有更好的方法吗?
我会注意到,我已经尝试在不是对象URL的字符串上调用URL.revokeObjectURL
,并且似乎可以正常工作,所以我还不清楚我正确确定它有多重要是否需要释放URL。
Note :这是一个打字稿脚本,但我认为该问题在JavaScript中同样有效,因此我已经标记了这两个。
你是对的,我认为目前根本没有其他方法。
这是正确的方法吗?
是。
更详细地:
目前,我正在这样做的方法就是检查URL是否以
'blob:'
开头。这是正确的方法吗?有更好的方法吗?
我们可以通过咨询定义URL.revokeObjectURL(url)
应如何工作的规范来确定找出答案
(重点是我的,以及对子指导的引用)
https://w3c.github.io/fileapi/#dfn-revokeobjecturl
revokeObjectURL(url)
静态方法必须运行以下步骤:
- 让
url record
是解析url
的结果。- 如果
url record
的方案不是"blob
&quort返回。- 让
origin
是url record
的起源。- 令
settings
为当前设置对象。- 如果
origin
与settings
的起源不同,请返回。- 从Blob URL商店中删除
url
的条目:
- 让商店成为用户代理的blob URL商店;
- 令URL字符串为序列化URL的结果。
- 删除存储
url string
。
- 从
map
中删除与给定条件相匹配的所有条目(即相等的url
)- ... 或者如果没有任何事情。
此外,观察到规格还指出:
这意味着试图撤销未注册的URL而不是抛出某种错误,而是会默默失败。如果发生这种情况,用户代理可能会在错误控制台上显示消息。
因此,我们可以得出结论:
- 如果URI的方案是
blob:
,或者string
URL以blob:
开头,则是 blob url 。- ...因此,它 May 被脚本(在同一来源上)撤销
URL.revokeObjectURL(url)
。
- ...因此,它 May 被脚本(在同一来源上)撤销
- 如果
URL.revokeObjectURL(url)
与无效的URL一起使用,那么(例如抛出的Error
或其他运行时异常)都不会发生。无效URL的示例包括:- 非
blob:
方案URL(由于步骤2) - 不同的原始URL(由于步骤5)
- 已经被撤销的objecturls(由于步骤6.3.2)
- 语法上有效的,相同的原始
blob:
包含伪造的UUID的URL(也是由于步骤6.3.2)
- 非
附录:匹配blob:
对象URL的常规表达:
Web文件API规范还规定了blob:
URI的特定格式,这意味着它们也可以通过常规表达RegExp
匹配(假设规范不会更改):
- 令
result
为空字符串。- 附加字符串"
blob:
到result
。- 令
settings
为当前设置对象- 让
origin
成为设置的起源。- 让
serialized
成为原始的ASCII序列化。- 如果
serialized
为" null",则将其设置为实现定义的值。- 附加序列化到
result
。- 附加
U+0024
Solidus(/)到result
。- 生成UUID RFC4122作为字符串,并将其附加到
result
。- 返回
result
- 该算法可以生成的BLOB URL的示例是
blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f64
。
因此,JS中的RegExp
就是这样(基于此REGEXP以匹配HTTP Origin字符串):
const blobObjectUrlRegex = /^blob:(?<origin>[w+]+://(?=.{1,254}(?::|$))(?:(?!d|-)(?![a-z0-9-]{1,62}-(?:.|:|$))[a-z0-9-]{1,63}b(?!.$).?)+(:d+)?)/(?<uuid>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
function isBlobOrObjectUrl( url ) {
return ( typeof url === 'string' ) && blobObjectUrlRegex.test( url );
}
演示:
const objectUrlExample = 'blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f64';
const regex = /^blob:(?<origin>[w+]+://(?=.{1,254}(?::|$))(?:(?!d|-)(?![a-z0-9-]{1,62}-(?:.|:|$))[a-z0-9-]{1,63}b(?!.$).?)+(:d+)?)/(?<uuid>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
console.log( "Is "%s" an ObjectURL (aka Blob URL)? %o", objectUrlExample, regex.test( objectUrlExample ) ? "Yes" : "No" );
const nonObjectUrlExample = 'https://stackoverflow.com/questions/45941639/proper-way-to-check-if-a-url-is-the-result-of-a-createobjecturl-call';
console.log( "Is "%s" an ObjectURL (aka Blob URL)? %o", nonObjectUrlExample, regex.test( nonObjectUrlExample ) ? "Yes" : "No" );