JavaScript判断图片是否存在的函数首次调用失效问题求助
JavaScript判断图片是否存在的函数首次调用失效问题求助
兄弟,你猜的完全没错!这个问题就是因为JavaScript加载图片是异步操作导致的~
你当前的代码里,创建Image实例后立刻去判断img.height,这时候图片还在加载过程中(甚至可能还没开始加载),所以height还是0,自然会返回原匹配内容;而第二次调用时,浏览器已经把图片缓存下来了,设置src后图片瞬间加载完成,height就能正确获取到,所以函数就正常工作了。
因为你不能用npm包,那我给你两个纯原生JS的解决方案,你可以根据自己的场景选:
方案一:提前预加载所有Emoji图片
如果知道所有可能用到的Emoji名称,可以在页面初始化的时候就把这些图片预加载一遍,把存在的图片记录下来,这样后续replacer调用时直接从缓存的记录里判断就行:
// 用来记录哪些Emoji图片存在的Map const emojiExists = new Map(); // 预加载Emoji的函数 function preloadEmojis(possibleEmojiNames) { possibleEmojiNames.forEach(name => { const img = new Image(); // 加载成功,标记为存在 img.onload = () => emojiExists.set(name, true); // 加载失败(比如图片不存在),标记为不存在 img.onerror = () => emojiExists.set(name, false); img.src = `./img/emoji/${name}.png`; }); } // 假设你有所有可能的Emoji名称列表,替换成你实际的列表就行 preloadEmojis(['smile', 'cry', 'laugh', 'heart']); // 修改你的replacer函数 this.replacer = function (match, name) { // 直接从预加载的记录里判断 if (emojiExists.get(name)) { return `<img class="emoji" src="./img/emoji/${name}.png" title="${name}" height="20px">`; } else { return match; } };
方案二:异步批量处理替换
如果不知道所有Emoji名称,或者不想预加载太多图片,可以先把文本里所有匹配的Emoji名称收集起来,批量检查图片是否存在,再完成替换:
// 异步替换Emoji的函数,需要传入你的文本和匹配用的正则 function replaceEmojisAsync(text, emojiRegex) { // 先找出所有匹配的Emoji名称,去重 const matches = [...text.matchAll(emojiRegex)]; const uniqueNames = [...new Set(matches.map(item => item[1]))]; // 批量检查每个名称对应的图片是否存在 return Promise.all(uniqueNames.map(name => { return new Promise(resolve => { const img = new Image(); img.onload = () => resolve({ name, exists: true }); img.onerror = () => resolve({ name, exists: false }); img.src = `./img/emoji/${name}.png`; }); })).then(checkResults => { // 把检查结果转成Map方便查询 const emojiMap = new Map(checkResults.map(result => [result.name, result.exists])); // 执行替换 return text.replace(emojiRegex, (match, name) => { if (emojiMap.get(name)) { return `<img class="emoji" src="./img/emoji/${name}.png" title="${name}" height="20px">`; } else { return match; } }); }); } // 使用示例: // 替换成你实际用来匹配Emoji的正则 const emojiRegex = /:([a-z]+):/g; // 传入要处理的文本 replaceEmojisAsync("Hello :smile:! How are you :cry:?", emojiRegex).then(updatedText => { // 把替换后的文本插入到DOM里,比如: document.getElementById('content').innerHTML = updatedText; });
这样就能解决首次调用失效的问题啦~
备注:内容来源于stack exchange,提问作者Landon Kuehner
相关产品推荐
相关产品推荐

