less 如何决定调用当前fileManager
loadFile
或loadFileSync
fileManager
? 根据此代码,它需要设置isSync
参数。 但是对getFileManager
调用的简短搜索显示此选项仅由lib/less/functions/data-uri.js
。
调用render()
时是否可以显式设置此选项?
isSync 可以传入 options 对象进行渲染。 data-uri 总是
同步,因为函数不能是异步的。
但是importManager
不会将任何选项传递给getFileManager
...
它在这里完成
这是因为该选项被较少的核心忽略并且仅特定于浏览器。 所以浏览器总是被称为 async 并且可能取决于选项使用同步或异步机制来获取文件。
我可以看出这有多令人困惑。 它会导致问题吗?
我立即看到的一件事是,它将在页面加载时受到选项的影响,因此如果它是在之后设置或作为选项传入的,它将被忽略。
好吧,可能我必须解释一下我的用例:
我为webpack编写了一个less-loader 。 由于 webpack 有自己的解析机制,我使用插件通过文件管理器连接到较少的文件解析。
Webpack 支持同步和异步加载器,但我还没有找到告诉 less 同步或异步渲染所有文件的方法。 目前它总是调用loadFile
。 因此,当请求同步编译时,我使用了一个肮脏的 hack来调用loadFileSync
。 幸运的是,当回调被同步调用时,同步工作较少(当然在正常情况下不应该这样做)。
我懂了...
我认为我们应该将异步选项移到较少的上下文中,然后使用它来确定按照您的建议进行哪个调用。 它可能需要对浏览器文件管理器进行一些更改,但我认为这将是一个很好的重构。
凉爽的!
只有一个问题:在接受callback
(就像render
- 函数所做的那样)的同时同步做某事是非常不寻常的。 您建议使用sync
-option 如下:
less.render(
input,
{ ... sync: true ... },
function (err, result) {
}
);
?
恕我直言,同步调用回调很奇怪。 我希望有这样的 api:
// async
less.render(input, option, callback);
// sync
var result = less.renderSync(input, option);
是的,你是对的,这样更好。
+1
考虑实现renderSync
以仅在回调中不限制代码执行似乎也非常有用。 在回调范围内,许多方法如console.err
或throw new Error()
或故意的 JavaScript 错误不会向控制台打印任何内容,只会停止代码执行,可能会导致无法追踪的错误。 我想这种行为不应该发生。
在我的特定情况下, renderSync
将用于命令行实用程序,而不是使用 Promise 来控制回调流以确保每次都按顺序打印所有输出和错误,我宁愿只使用 renderSync 而不是担心它。
(不是贬低问题本身,只是为了确保它不会变得比现在更奇怪):
恕我直言,同步调用回调很奇怪。
这是夸大其词...在这行代码中,您没有假设配置是异步设置的,是吗?
回调只是回调,它们本身与同步/异步内容无关。
PS只是为了澄清更多:
@kwketh
这个less.render
表单已经存在多年了,你不能只是从无到有改变它来破解无数的片段。
@七阶段最大
非常感谢您的回答,他们都很有帮助。 我同意你关于回调的所有观点。 我对.render
代码进行了非常简短的查看,您是对的,它的编写形式,全部围绕回调展开,拥有renderSync
似乎既不容易也不合理。
我的问题在某种程度上不同但相关(https://github.com/less/less.js/issues/2546)。 实现renderSync
功能将解决我的问题,但它不会是最终的解决方案。
你介意快速浏览一下吗? 我真的很感激。
谢谢。
有人只是使用了太多节点
嗯,这是真的 :grin:
但是节点的回调约定是公认的。 在这种情况下,我假设回调总是被异步调用。
另外:出现错误时如何处理错误? 它是抛出(像大多数同步 API 一样)还是作为参数传递给回调?
只是当前的 API 不明确(至少恕我直言)
有没有renderSync
? 如果没有,是否有同步render
的解决方法?
编辑:Nvm。 对于任何偶然发现此问题的未来人,这就是我所做的:
less.renderSync = function (input, options) {
if (!options || typeof options != "object") options = {};
options.sync = true;
var css;
this.render(input, options, function (err, result) {
if (err) throw err;
css = result.css;
});
return css;
};
这个功能真的实现了吗? 有什么文件吗? 我只能找到async
。
我知道它是否真的得到支持,但我知道我目前所做的工作对我有用,所以......耸耸肩
@Aarilight非常感谢你,你的代码帮助很大
这种同步回调行为确实违反直觉 :confused:
@Aarilight它对我不起作用=(
我试过
less.render(css, {sync : true}, (e, result) =>{
if(e) {
console.error(e)
}
output = result;
return result
});
并登录https://github.com/less/less.js/blob/master/lib/less/render.js
console.log('1')
this.parse(input, options, function(err, root, imports, options) {
console.log('2')
if (err) { return callback(err); }
var result;
console.log('3')
try {
console.log('4')
var parseTree = new ParseTree(root, imports);
console.log('5')
result = parseTree.toCSS(options);
}
catch (err) {
console.log('6')
return callback(err);
}
console.log('7')
callback(null, result);
});
console.log('8')
我看到一些文件的 1, 8 然后是 2,3,4,5,6,7
-1 将渲染拆分为render
和renderSync
。 这是一个尴尬的 Node.js 约定。 并且它不允许将同步选项发送到 grunt/gulp/accord 或其他集成到 less 中的工作流,这些工作流将 JS 对象传递给指定的函数。 IMO 可以在使用异步选项时传入可选回调。
另一种选择:我看到图书馆开始做的实际上是在任何一种情况下都返回一个承诺。 然后,同步/异步之间的所有变化都在承诺完成时,但处理结果的代码完全相同。
顺便说一句:
{sync: true}
没有这样的选择。
-1 将渲染拆分为渲染和渲染同步。 这是一个尴尬的 Node.js 约定。
这不是完全主观的观点吗? 恕我直言,在单个函数中结合 async 和 sync 是(除了少数例外)一个可怕的反模式。 它创建的代码与条件语句杂乱无章,更难维护,甚至比明确定义和记录的函数更好地完成一件事更让用户感到困惑。 只是我的 2c
这不是完全主观的观点吗?
是的。
无论如何,我的另一点不是主观的。 也就是说,如果函数被拆分,则在可能需要更新的构建过程中使用 Less。 例如:我目前用于一个项目的 Accord (https://github.com/jenius/accord),将不同的编译器抽象成一个 API,并且通常将一个对象传递给引擎需要的任何功能。 因此,根据开发人员指定的 Less 选项切换使用哪个函数可能不是什么大问题,但我不确定会影响多少个库。 这只是需要注意的事情。
截至目前,在我的选项中添加syncImport: true
为我解决了这个问题。
(它不在文档中......我很幸运在源代码中偶然发现了它)
此问题已自动标记为过时,因为它最近没有活动。 如果没有进一步的活动发生,它将被关闭。 感谢你的贡献。
最有用的评论
有没有
renderSync
? 如果没有,是否有同步render
的解决方法?编辑:Nvm。 对于任何偶然发现此问题的未来人,这就是我所做的: