Less.js: 如何触发同步和异步导入

创建于 2014-12-07  ·  26评论  ·  资料来源: less/less.js

less 如何决定调用当前fileManager loadFileloadFileSync fileManager ? 根据此代码,它需要设置isSync参数。 但是对getFileManager调用的简短搜索显示此选项仅由lib/less/functions/data-uri.js

调用render()时是否可以显式设置此选项?

feature request medium priority stale

最有用的评论

有没有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;
};

所有26条评论

isSync 可以传入 options 对象进行渲染。 data-uri 总是
同步,因为函数不能是异步的。

但是importManager不会将任何选项传递给getFileManager ...

它在这里完成

https://github.com/less/less.js/blob/32dbbee247f76af00eb7577053eccad2ee5f6110/lib/less-browser/file-manager.js#L61

这是因为该选项被较少的核心忽略并且仅特定于浏览器。 所以浏览器总是被称为 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.errthrow new Error()或故意的 JavaScript 错误不会向控制台打印任何内容,只会停止代码执行,可能会导致无法追踪的错误。 我想这种行为不应该发生。

在我的特定情况下, renderSync将用于命令行实用程序,而不是使用 Promise 来控制回调流以确保每次都按顺序打印所有输出和错误,我宁愿只使用 renderSync 而不是担心它。

(不是贬低问题本身,只是为了确保它不会变得比现在更奇怪):

恕我直言,同步调用回调很奇怪。

这是夸大其词...在这行代码中,您没有假设配置是异步设置的,是吗?
回调只是回调,它们本身与同步/异步内容无关。

好的,我们需要谈论术语callback : wink:。

我知道,有些调用函数传递给forEach a callback (如MDN )。 我不会这么称呼它,因为对我来说,回调是在任务完成时调用的东西。

如果回调遵循节点的错误约定,第一个参数是null或错误,那么有充分的理由_always_ 异步调用它。

我知道,有些调用函数传递给forEach一个回调`

有人只是使用了太多node ;)每个人都将这个东西命名为“回调”。 因此,如果是关于“在任务完成时调用的回调函数”,那么它不亚于“异步回调”。

但是没关系,抱歉,我并不是想听起来像一个 CO 并开始这场纯粹的语言辩论(只是想确保我们说相同的语言并且文档实际上提到less.render是同步的)。

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 将渲染拆分为renderrenderSync 。 这是一个尴尬的 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为我解决了这个问题。

(它不在文档中......我很幸运在源代码中偶然发现了它)

此问题已自动标记为过时,因为它最近没有活动。 如果没有进一步的活动发生,它将被关闭。 感谢你的贡献。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

BrianMulhall picture BrianMulhall  ·  4评论

matthew-dean picture matthew-dean  ·  6评论

heavyk picture heavyk  ·  3评论

joe223 picture joe223  ·  4评论

pknepper picture pknepper  ·  3评论