javascript - 带有异步数据的 lodash.template
问题描述
我真的很喜欢_.template函数,我用它来允许用户在他的文本中输入变量,我以后用它来替换一些数据。
唯一的问题是我需要在调用编译的模板函数之前收集所有可选变量数据,这个过程可能需要一些时间,在某些情况下可能是多余的,因为用户不会总是使用所有可选变量。
例如,假设用户发送如下字符串:
ZimGil is <%= age %> and his favorite language is <%= language %>
我需要有age
andlanguage
变量,但我不需要有phone
需要一些冗余时间才能获得的变量。
试图找出一种方法来根据使用的变量评估模板中的异步函数
解决方案
您可以使用正则表达式来获取所有变量名称。
您需要遵循 lodash 允许变量获取所有变量的方法。请参阅模式每个部分旁边的注释以获取解释。
TL;DR:正则表达式是/\<\%[=|-]?(?:[\s]|if|\()*(.+?)(?:[\s]|\)|\{)*\%\>/g
(没有字符串转义)。
function getTemplateVariables(template) {
// making sure the template is a string
template = template || '';
const pattern = [
'<%[=|-]?', // look for opening tag (<%, <%=, or <%-)
'(?:[\\s]|if|\\()*', // accept any space after opening tag and before identifier
'(.+?)', // capture the variable name (`luigi` in <%= luigi %>)
'(?:[\\s]|\\)|\\{)*', // accept any space after identifier and before closing tag
'%>' // look for closing tag
].join('');
const regex = new RegExp(pattern, 'g');
const matches = [];
let match;
while (match = regex.exec(template)) {
matches.push(match[1])
}
return _.uniq(matches);
}
_.uniq
用于删除重复的变量。
更改 lodash 中的模板函数
您可以使用mixin覆盖 lodash 中的模板函数并返回变量:
const originLodashTemplate = _.template;
_.mixin({
getTemplateVariables, // <-- you can use this on it's own
template: (...args) => { // <-- or together
const variables = _.getTemplateVariables(args[0]);
const template = originLodashTemplate (...args);
return {
variables,
template
};
}
});
然后,您可以像这样使用它:
const templateObj = _.template(
"ZimGil is <%= age %> and his favorite language is <%= language %>"
);
console.log(templateObj.variables);
// will print ["age","language"]
console.log(templateObj.template({ age: "over 5000 years old", language: "turtlese" }));
// will print 'ZimGil is over 5000 years old and his favorite language is turtlese'
异步示例
(async () => {
const templateObj = _.template(
"ZimGil is <%= age %> and his favorite language is <%= language %>"
);
const templateData = {};
for (const variable of templateObj.variables) {
const asyncResult = await mapToAsyncCall(variable);
templateData[variable] = asyncResult;
}
// this data will only contain existing variables
templateObj.template(templateData);
})();
工作示例
这是一个代码笔,其中包含所有这些工作的示例。
注意
- 尽管我很确定覆盖
_.template
是安全的(不要认为它与 lodash 内部的全局指针一起使用),但它可能不是,你可能想给 mixin 函数一个不同的名字! - 这不会涵盖高级代码注入,例如
_.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
. 您需要将您计划允许的单词添加到正则表达式中,以支持更多识别变量的代码注入。目前,它仅涵盖if
语句,但可以在上面的“打开标签之后和之前”正则表达式中添加更多内容。一种完全做到这一点的方法(但这更复杂)是更改原始源代码_.template
以实际返回变量并用新代码覆盖它。这将支持 lodash 开箱即用的所有代码注入。
推荐阅读
- spring-boot - 如何检测过期的 OAuth2 令牌?
- javascript - 根据请求路径初始化变量而不使用多个if条件?
- vb.net - 从文本框中的一行到另一行的单词输入
- c++ - 将数组的地址分配给变量并删除
- python - Python 将值均匀分配到字典中的列表
- xml - 使用 XML Schema xs:key 和 xs:keyref 未找到 keyRef 的引用值
- python - 一个对等对象处理多个客户端
- python - Python:从列表中获取 n 个可能的最小 m 值集
- python-3.x - Spark 在到达过滤器功能时杀死作业,错误火花请求执行器仅在粗粒度模式下支持
- javascript - 如何绑定一个