Funções preguiçosas de JavaScript

Oi


Eu pensei aqui para falar sobre como, em JavaScript, usando a biblioteca Fluture, você pode criar e usar funções lazy. Esta será uma breve visão geral sobre como criar funções, como lidar com erros e um pouco sobre simultaneidade. Cérebros de programação funcional Eu não vou subir! Eu prometo!


Fluture


Fluture é uma biblioteca desenvolvida pelo desenvolvedor Aldwin Vlasblom que implementa o Future. O futuro é uma alternativa ao Promise, que possui uma API muito mais poderosa que permite implementar cancelamento, "recursão" segura, execução "sem erros" (usando o Either) e um pequeno carrinho de recursos interessantes.


Acho que vale a pena falar sobre os métodos (mônadas) que usarei nos exemplos abaixo.


  • .of(Any) - cria um futuro a partir do valor passado
  • .map(Function) - não, isso não é Array.map , é uma função de transformação semelhante a Promise.then
  • .chainRej(Function) - como Promise.catch pega um erro
  • .fork(Function, Function) - inicia execução futura

Criando uma função lenta


Para mim, destaquei duas abordagens principais para criar funções preguiçosas no Fluture. A primeira abordagem é que criamos uma função que aceita os dados de origem e retorna um futuro pronto para execução. A segunda abordagem é que criamos um futuro com todas as transformações descritas e passamos os dados para ele.


Não está claro Vamos dar um exemplo! Nós temos essa função


 const multiply10 = x => x * 10; 

Agora faça-a preguiçosa usando a primeira abordagem


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

Muito volumoso, não é? Vamos tentar escrever de forma mais concisa usando a segunda abordagem.


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

Já é melhor, mas ainda complicado. Deve ser mais compacto!


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

De fato, essas abordagens não são mutuamente exclusivas e podem ser usadas juntas.


 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 

Tratamento de erros


O tratamento de erros no futuro praticamente não difere do tratamento de erros no Promise. Vamos lembre-se imagine uma função que faça uma solicitação a uma API de terceiros, não muito estável.


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

Mesma função, mas envolvida no 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 fato, o tratamento de erros pode ser mais flexível. Para fazer isso, precisamos da estrutura Either, e essa pequenez está além do escopo da minha revisão.


Concorrência


Para trabalhar com o paralelismo, o Future implementa dois métodos race(Futures[]) (semelhante ao Promise.race ), parallel(n, Futures[]) e both(Future, Future) , mas é um caso especial de parallel .


O método parallel usa dois argumentos, o número de Future paralelo e a matriz com Future. Para tornar o comportamento parallel o mesmo que o método Promise.all , você precisa definir o número de Promise.all para definir como Infinity .


Aqui também não podemos ficar sem exemplos.


 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] 

Promessa Compatível


Não há lugar para promessa no JavaScript, e é improvável que alguém fique feliz se o seu método retornar algum futuro obscuro. Para fazer isso, o Future possui um método .promise() , que iniciará a execução do Future e o envolverá no Promise.


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

Referências



Talvez isso seja tudo o que eu queria lhe contar. Se o tópico for interessante, deixe-me saber, vou falar mais sobre o tratamento de erros. E sim, não me repreenda muito, este é o meu primeiro post no Habré.

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


All Articles