JavaScript提及脚本问题:含空格用户名不生效及性能优化需求
解决你的JavaScript提及脚本问题
嘿,很高兴能帮你优化这个提及脚本!咱们一步步搞定你遇到的两个问题:
问题1:支持带空格的用户名
你当前用的正则/@(\w+)?/g里,\w只能匹配字母、数字和下划线,完全不包含空格,所以带空格的用户名根本触发不了匹配逻辑。咱们得调整正则,让它能识别带空格的用户名,同时还要避免无限制匹配(比如一直匹配到文本结尾)。
推荐替换成这个正则:
/@([\w\s]+?)(?=\s|$|[,.;!])/g
[\w\s]+?:匹配字母、数字、下划线和空格,+?是非贪婪模式,确保匹配到下一个空格、标点或者文本结尾就停止,不会过度匹配(?=\s|$|[,.;!]):正向预查,明确指定匹配的终止边界,避免把后面无关的内容也包含进来
问题2:优化性能
你原来的代码每次匹配都要做两次数据库查询(count()和findOne()),如果文本里有多个提及,这会产生大量重复的数据库请求,性能肯定拉胯。咱们改成批量查询+本地缓存的方式,能大幅提升效率:
修改后的完整代码
// 第一步:提取所有匹配的用户名并去重 const mentionMatches = content.match(/@([\w\s]+?)(?=\s|$|[,.;!])/g) || []; const targetUsernames = mentionMatches .map(mention => mention.slice(1)) // 去掉开头的@ .filter((name, index, self) => self.indexOf(name) === index); // 去重,避免重复查询 // 第二步:批量查询数据库,一次性获取所有存在的用户 const existingUsers = Meteor.users.find({ username: { $in: targetUsernames } }).fetch(); // 把用户信息存进对象,方便后续O(1)查找 const userLookupMap = {}; existingUsers.forEach(user => { userLookupMap[user.username] = user; }); // 第三步:替换内容,直接从本地缓存取数据 content = content.replace(/@([\w\s]+?)(?=\s|$|[,.;!])/g, function(match, username) { if (userLookupMap[username]) { return `<a href=''>@${userLookupMap[username].username}</a>`; } else { return match; // 保留原始的@+用户名,避免丢失@符号 } });
性能优化点说明
- 把N次数据库请求合并成1次,大幅减少数据库交互开销
- 用对象
userLookupMap做本地缓存,替换时直接快速查找,比每次查数据库高效得多 - 去重处理避免重复查询同一个用户名,进一步减少无效请求
另外,你原来的else分支返回contents会丢失开头的@符号,我改成返回match,这样未匹配到的用户还能保留@用户名的原始格式,逻辑更合理。
内容的提问来源于stack exchange,提问作者P. Nick
相关产品推荐
相关产品推荐

