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)
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);
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);
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);
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);
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();
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é.