Suponha que você mantenha uma biblioteca que expõe uma função getData
. Seus usuários chamá-lo para obter dados reais:
var output = getData();
Sob a dados capô é salvo em um arquivo para que você implementado getData
usando Node.js built-in fs.readFileSync
. É óbvio ambos getData
e fs.readFileSync
são funções de sincronização. Um dia, foi solicitado que você alternasse a fonte de dados subjacente para um repositório como o MongoDB, que só pode ser acessado de forma assíncrona. Você também foi instruído a evitar irritar seus usuários. A getData
API não pode ser alterada para retornar apenas uma promessa ou exigir um parâmetro de retorno de chamada. Como você atende a ambos os requisitos?
Função assíncrona usando retorno de chamada / promessa é o DNA de JavasSript e Node.js. Qualquer aplicativo JS não trivial provavelmente é permeado por esse estilo de codificação. Mas essa prática pode facilmente levar à chamada pirâmide de destruição de retorno de chamada. Pior ainda, se qualquer código em qualquer chamador na cadeia de chamadas depende do resultado da função assíncrona, esse código também deve ser envolvido na função de retorno de chamada, impondo uma restrição de estilo de codificação ao chamador. De tempos em tempos, acho necessário encapsular uma função assíncrona (geralmente fornecida em uma biblioteca de terceiros) em uma função de sincronização para evitar uma re-fatoração global maciça. Procurar uma solução sobre esse assunto geralmente terminava com fibras de nóou pacotes npm derivados dele. Mas as fibras simplesmente não conseguem resolver o problema que estou enfrentando. Até o exemplo fornecido pelo autor da Fibers ilustrou a deficiência:
...
Fiber(function() {
console.log('wait... ' + new Date);
sleep(1000);
console.log('ok... ' + new Date);
}).run();
console.log('back in main');
Saída real:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
Se a função Fiber realmente transformar a função assíncrona em suspensão em sincronização, a saída deverá ser:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
back in main
Eu criei outro exemplo simples no JSFiddle e procurando por código para produzir a saída esperada. Aceitarei uma solução que só funcione no Node.js, para que você possa solicitar qualquer pacote npm, apesar de não trabalhar no JSFiddle.