Less.js: Cómo activar importaciones sincronizadas y asíncronas

Creado en 7 dic. 2014  ·  26Comentarios  ·  Fuente: less/less.js

¿Cómo decide Less llamar loadFile o loadFileSync del actual fileManager ? De acuerdo con este código , requiere que se establezca un parámetro isSync . Pero una búsqueda corta de una llamada a getFileManager revela que esta opción solo la utilizan lib/less/functions/data-uri.js .

¿Es posible establecer esta opción explícitamente al llamar a render() ?

feature request medium priority stale

Comentario más útil

¿Hay un renderSync todavía? Si no es así, ¿hay alguna solución para un render sincrónico?

Editar: Nvm. Para cualquier persona futura que se tope con esto, esto es lo que hice:

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

Todos 26 comentarios

isSync se puede pasar en el objeto de opciones para renderizar. data-uri es siempre
sincronizar porque las funciones no pueden ser asincrónicas.

Pero el importManager no pasa ninguna opción a getFileManager ...

Esta hecho aqui

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

Es porque esa opción es ignorada por menos núcleo y es específica solo para el navegador. Por lo tanto, el navegador siempre se llama async y, según las opciones, puede usar un mecanismo de sincronización o async para obtener el archivo.

Puedo ver lo confuso que es eso. ¿Está causando un problema?

Una cosa que veo de inmediato es que solo se verá afectado por las opciones al cargar la página, por lo que si se establece posteriormente o se pasa como una opción, se ignorará.

Bueno, probablemente tenga que explicar mi caso de uso:

Escribí un cargador menos para webpack . Dado que el paquete web tiene un mecanismo de resolución propio, estoy usando un complemento para conectarme a la resolución de archivos menos a través de un administrador de archivos.

Webpack admite cargadores sincronizados y asíncronos, pero no he encontrado una manera de decir menos para que todos los archivos se sincronicen o asincrónicamente. Actualmente siempre llama loadFile . Por lo tanto, utilicé un truco sucio para llamar a loadFileSync cuando se solicita una compilación sincrónica. Afortunadamente, menos funciona sincrónicamente cuando la devolución de llamada se llama sincrónicamente (lo que no debería hacerse en circunstancias normales, por supuesto).

Veo...

Creo que deberíamos mover una opción asincrónica para estar en menos contexto, luego usarla para determinar qué llamada hacer como sugiere. Puede que necesite algunos cambios en el administrador de archivos del navegador, pero creo que será un buen refactor.

¡Frio!

Solo hay un problema: es muy inusual hacer algo sincrónicamente aceptando un callback (como lo hace la función render ). Estás sugiriendo una opción sync como esta:

less.render(
    input,
    { ... sync: true ... },
    function (err, result) {
    }
);

?

En mi humilde opinión, es extraño que la devolución de llamada se llame sincrónicamente. Esperaría una api como esta:

// async
less.render(input, option, callback);

// sync
var result = less.renderSync(input, option);

Sí, tienes razón, eso es mejor.

+1
Parece que esto también es muy útil para considerar la implementación de renderSync para no restringir la ejecución del código solo en la devolución de llamada. En el alcance de la devolución de llamada, muchos métodos como console.err o throw new Error() o un error deliberado de JavaScript no imprimirán nada en la consola, solo detendrán la ejecución del código, lo que podría generar errores que no se pueden rastrear. Me imagino que este comportamiento no debería ocurrir.

En mi caso particular, renderSync se usaría en una utilidad de línea de comandos y en lugar de controlar el flujo de devolución de llamada usando promesas para garantizar que todos los resultados y errores se impriman en orden cada vez, prefiero usar renderSync y no tener preocuparse por eso.

(No degradando el problema en sí, sino solo para asegurarse de que no se vuelva aún más extraño de lo que es):

En mi humilde opinión, es extraño que la devolución de llamada se llame sincrónicamente.

Esto es una exageración ... En esta línea del código no está asumiendo que la configuración se establece de forma asincrónica, ¿verdad?
Las devoluciones de llamada son solo devoluciones de llamada, por sí mismas no tienen nada que ver con cosas de sincronización / asincronía.

Ok, entonces tenemos que hablar sobre el término callback : wink :

Lo sé, algunas funciones de llamada pasan a forEach a callback (como MDN ). No lo llamaría así, porque para mí una devolución de llamada es algo que se llama cuando se ha terminado una tarea.

Y si la devolución de llamada sigue la convención de error del nodo con el primer argumento null o un error, entonces hay buenas razones para _siempre_ llamarlo de forma asincrónica.

Lo sé, algunas funciones de llamada pasan a forEach una devolución de llamada`

Alguien está usando demasiado node ;) Todos nombran esto como una "devolución de llamada". Entonces, si se trata de "una función de devolución de llamada llamada cuando una tarea ha finalizado", no es más ni menos que "devolución de llamada asincrónica".

Pero no importa, lo siento, no quise sonar como un CO y comenzar este debate puramente lingüístico (solo quería asegurarme de que hablamos el mismo idioma y los documentos realmente mencionan que less.render es sincrónico).

PD Solo para aclarar más:

@kwketh

Este formulario less.render estuvo ahí durante años, no puedes simplemente tomarlo y cambiarlo de la nada para romper trillones de fragmentos.

@ siete-fases-max

Muchas gracias por tus respuestas, todas son útiles. Estoy de acuerdo con todos sus puntos con respecto a las devoluciones de llamada. Eché un vistazo muy breve al código .render y tienes razón, la forma en que está escrito, todo gira en torno a las devoluciones de llamada y no parece ni fácil ni razonable tener renderSync .

Mi problema es de alguna manera diferente pero relacionado (https://github.com/less/less.js/issues/2546). La implementación de la función renderSync resolvería mi problema, pero no sería la solución definitiva.

¿Te importaría echar un vistazo rápido? Realmente lo apreciaria.

Gracias.

Alguien está usando demasiado nodo

Bueno, eso es cierto: sonrisa:

Pero la convención de devolución de llamada del nodo está bien establecida. Asumiría que la devolución de llamada siempre se llamará de forma asincrónica en este caso.

Además: ¿Cómo se manejan los errores cuando hubo un error? ¿Se lanza (como la mayoría de las API de sincronización) o se pasa como argumento a la devolución de llamada?

Es solo que la API actual es ambigua (al menos en mi humilde opinión)

¿Hay un renderSync todavía? Si no es así, ¿hay alguna solución para un render sincrónico?

Editar: Nvm. Para cualquier persona futura que se tope con esto, esto es lo que hice:

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

¿Está realmente implementada esta función? ¿Existe alguna documentación? Solo puedo encontrar la opción async .

No sé si realmente es compatible, pero sé que lo que hice me funciona actualmente, así que ... encogerse de hombros

@Aarilight muchas gracias, tu código ayudó mucho

Este comportamiento de devolución de llamada sincrónica es realmente contrario a la intuición: confuso:

@Aarilight no me funciona = (
Lo intenté

less.render(css, {sync : true}, (e, result) =>{
        if(e) {
         console.error(e)
    }

        output = result;
        return result
    });

y registrado 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')

Y veo 1, 8 y luego 2,3,4,5,6,7 para algunos archivos

-1 para dividir el renderizado en render y renderSync . Es una convención de Node.js que es incómoda. Y no permite enviar una opción de sincronización a gruñir / tragar / acordar u otros flujos de trabajo integrados en menos que pasan en un objeto JS a una función designada. En mi opinión, está bien pasar una devolución de llamada opcional cuando se usa una opción asíncrona.

Otra opción: lo que he visto que las bibliotecas comienzan a hacer es devolver una promesa en cualquier caso. Entonces, todo lo que cambia entre sync / async es cuando se cumple la promesa, pero el código que maneja el resultado es exactamente el mismo.

Y por cierto:

{sync: true}

No existe tal opción.

-1 para dividir render en render y renderSync. Es una convención de Node.js que es incómoda.

¿No es ese un punto de vista completamente subjetivo? En mi humilde opinión, la combinación de async y sync en una sola función es (con pocas excepciones) un terrible anti-patrón. Crea código repleto de declaraciones condicionales, es más difícil de mantener e incluso más confuso para el usuario que una función claramente definida y documentada que hace una cosa bien. solo mi 2c

¿No es ese un punto de vista completamente subjetivo?

Si.

Independientemente, mi otro punto no es subjetivo. Es decir, que Less se usa en procesos de compilación que podrían necesitar actualizarse si se divide una función. Por ejemplo: Accord (https://github.com/jenius/accord), que utilizo actualmente para un proyecto, extrae diferentes compiladores en una sola API y, por lo general, pasa un objeto a cualquier función que requiera ese motor. Por lo tanto, probablemente no sea un gran problema cambiar qué función se usa en función de las opciones Menos que especifica un desarrollador, pero no estoy seguro de cuántas bibliotecas afectaría. Es algo de lo que hay que estar consciente.

A partir de ahora, agregar syncImport: true a mis opciones solucionó esto para mí.

(No está en la documentación ... tuve la suerte de encontrarlo en el código fuente)

Este problema se ha marcado automáticamente como obsoleto porque no ha tenido actividad reciente. Se cerrará si no se produce más actividad. Gracias por sus aportaciones.

¿Fue útil esta página
0 / 5 - 0 calificaciones