Funciones perezosas de JavaScript

Hola


Pensé aquí para contarte cómo en JavaScript, usando la biblioteca Fluture, puedes crear y usar funciones perezosas. Esta será una breve descripción general sobre cómo crear funciones, cómo manejar errores y un poco sobre la concurrencia. ¡Cerebros de programación funcional que no volaré! Lo prometo!


Fluture


Fluture es una biblioteca desarrollada por el desarrollador Aldwin Vlasblom que implementa Future. Future es una alternativa a Promise, que tiene una API mucho más poderosa que permite implementar la cancelación, la "recursión" segura, la ejecución "libre de errores" (usando Either) y un pequeño conjunto de características geniales.


Creo que vale la pena contarles sobre los métodos (mónadas) que usaré en los ejemplos a continuación.


  • .of(Any) : crea un futuro a partir del valor pasado
  • .map(Function) - no, esto no es Array.map , esta es una función de transformación similar a Promise.then
  • .chainRej(Function) - como Promise.catch un error
  • .fork(Function, Function) - comienza la ejecución futura

Crear una función perezosa


Para mí, destaqué dos enfoques principales para crear funciones perezosas en Fluture. El primer enfoque es que creamos una función que acepta los datos de origen y devuelve un futuro listo para su ejecución. El segundo enfoque es que creamos un Futuro con todas las transformaciones descritas y luego le pasamos los datos.


No está claro ¡Tomemos un ejemplo! Tenemos tal función


 const multiply10 = x => x * 10; 

Ahora hazla floja usando el primer enfoque


 const multiply10 = x => x * 10; const lazyMultiply10 = (x) => Future .of(x) //  Future   .map(multiply10); //     lazyMultiply10(2).fork(console.error, console.log); // -> 20 

Demasiado voluminoso, ¿no? Intentemos escribir de manera más concisa usando el segundo enfoque.


 const multiply10 = x => x * 10; const lazyMultiply10 = Future.map(multiply10); const value = Future.of(2); //     Future lazyMultiply10(value).fork(console.error, console.log); // -> 20 

Ya mejor, pero aún engorroso. ¡Debe ser más compacto!


 const lazyMultiply10 = Future.map(x => x * 10); lazyMultiply10(Future.of(2)).fork(console.error, console.log); // -> 20 

De hecho, estos enfoques no son mutuamente excluyentes y pueden usarse juntos.


 const lazyMultiply10 = Future.map(x => x * 10); const someCalculation = a => Future .of(a) .map(v => v + 1) .chain(v => lazyMultiply10(Future.of(v)); someCalculation(10).fork(console.error, console.log); // -> 110 

Manejo de errores


El manejo de errores en el futuro prácticamente no es diferente del manejo de errores en Promise. Vamos recuerda imagine una función que realiza una solicitud a una API de terceros, no muy estable.


 const requestToUnstableAPI = query => request({ method: 'get', uri: `http://unstable-site.com/?${query}` }) .then(res => res.data.value) .catch(errorHandler); 

La misma función, pero envuelta en el futuro


 const lazyRequestToUnstableAPI = query => Future .tryP(() => request({ method: 'get', uri: `http://unstable-site.com/?${query}` })) .map(v => v.data.value) .chainRej(err => Future.of(errorHandler(err)); 

De hecho, el manejo de errores se puede hacer más flexible. Para hacer esto, necesitamos la estructura Oither, y esta pequeñez está más allá del alcance de mi revisión.


Concurrencia


Para trabajar con paralelismo, Future implementa dos métodos race(Futures[]) (similar a Promise.race ), parallel(n, Futures[]) y both(Future, Future) , pero es un caso especial de parallel .


El método parallel toma dos argumentos, el número de Future paralelo y la matriz con Future. Para hacer que el comportamiento parallel el mismo que el método Promise.all , debe establecer el número de Promise.all para establecer como Infinity .


Aquí tampoco podemos prescindir de ejemplos.


 const requestF = o => Future.tryP(() => request(o)); const parallel1 = Future.parallel(1); const lazyReqs = parallel1( [ 'http://site.com', 'http://another-site.com', 'http://one-more-site.com', ] .map(requestF) ); lazyReqs.fork(console.error, console.log); // -> [Result1, Result2, Result3] 

Promesa Compatible


No hay lugar para Promise en JavaScript, y es poco probable que alguien esté contento si su método devuelve un futuro oscuro. Para hacer esto, Future tiene un método .promise() , que comenzará la ejecución de Future y lo envolverá en Promise.


 Future .of(10) .promise(); // -> Promise{value=10} 

Referencias



Eso, tal vez, es todo lo que quería decirte. Si el tema es interesante, hágamelo saber, le contaré más sobre el manejo de errores. Y sí, no me regañes mucho, esta es mi primera publicación en Habré.

Source: https://habr.com/ru/post/es435838/


All Articles