loading...

Promise ou Observable - Mistérios do JavaScript.

kurybr profile image Jorge Rafael ・4 min read

Existem dois termos que são aplicados quando falamos desses conceitos; Eles são, Eager e Lazy ( ansioso e preguiçoso ) e a principal diferença entre os dois, são respectivamente as definições desse termos.

Como assim? Vou explicar logo abaixo.

Eager & Lazy

Vamos começar com o seguinte exemplo de Promise

const greetingEager = new Promise((resolve, reject) => { 
    console.log('Dentro da promise as coisas acontecem de forma anciosa.');
    resolve('Olá, Prazer em te conhece.');
})

greetingEager.then( res => console.log('Saudação na Promisse: ' + res ));

No exemplo acima conseguimos ver como ela é ansiosa, porque ao declarar a Promise o conteudo dela já é executado imediatamente, sem mesmo esperar ser invocada através do then.

Se você executar esse código acima verá que a mensagem do console.log dentro da Promise é executada antes mesmo de você chamar o then da função.

Ao contrário de um Observer, que por essência é preguiçoso.

//https://rxjs-dev.firebaseapp.com/guide/overview
const { Observable } = rxjs;

const greetingLazy = new Observable(observer => {
  console.log('Dentro de um observer as coisas acontecem de forma preguiçosa.');
  observer.next('Olá, fique a vontade.');
  observer.complete();
});

console.log('Antes de começar inscreva-se no Observer');

greetingLazy.subscribe({
  next: console.log,
  complete: () => console.log('Fim da conversa.')
});

Quando você cria um Observable, você precisa fornecer uma função de retorno de chamada através do atributo next, que será invocada sempre que for executado o next dentro do observer.

Para entender um pouco mais sobre isso, tem um post sobre Generator que pode te ajudar.

No exemplo acima a mensagem "Antes de começar inscreva-se no Observer" vai aparecer antes do console.log de dentro do Observable.

Um exemplo seria um cenário onde você quer obter uma informação sobre o cardápio de um restaurante. A promise, seria um menu na sua mesa. onde ao chegar o menu já está disponível para você. Enquanto o Observable, o menu só irá vir até você quando você pedir para um garçom trazer.

Sync & Async

Uma outra diferença é o tipo de execução um observable pode ser síncrono ou assíncrono dependendo do contexto, enquanto a Promise sempre vai ser assíncrona, mesmo que seja resolvida imediatamente após sua execução.


const greeting = new Promise((resolve, reject) => { 
    resolve('Olá, prazer em te conhecer.')
})

console.log('Antes de chamar a Promise')

greeting.then(res => console.log('Saudação da Promisse: ' + res ));

console.log("Depois de chamar o then na Promise provando que ela inicia sempre de maneira assíncrona.")

No exemplo acima, apesar da execução dessa promise ser imediata, você vai perceber ao rodar o código, que a mensagem de dentro da Promise aparecerá por ultimo. Isso porque uma vez que é declarada a Promise a chamada dela é adicionada a fila de microtasks, ela será só executada no fim da microtask atual.

const { Observable } = rxjs;

const greeting = new Observable(observer => {
  observer.next('Olá, Estou muito feliz em ver você');
  observer.complete();
});

console.log('Antes de chamar o subscribe do Observable');

greeting.subscribe({
  next: console.log,
  complete: () => console.log('Fim da saudação')
});

console.log('Depois de chamar o subscribe do Observable, provando que ele pode ser executado de forma síncrona')

No exemplo a cima, a ordem das mensagem serão mantidas. por seguir uma ordem de processos de execução de tasks.

Porém, podemos executar coisas dentro do Observable de forma assíncrona também, como no código a seguir.

const tiredGreeting = new Observable(observer => {
    setTimeout(() => {
      observer.next('Ah, hey, prazer em te conhecer');
      observer.complete();
    }, 2000);
});

console.log('Antes de chamar o subscribe do Observable');

tiredGreeting.subscribe({
    next: console.log,
    complete: () => console.log('Fim da saudação')
});

console.log('Depois de chamar o subscribe do Observable, provando que ele pode ser executado de forma assíncrona')

Valores

Um Observable pode emitir vários valores/resultados para enquanto estiver inscrito.

Enquanto a Promise retorna apenas um resultado, independente de quantas vezes você chame aquela mesma promise.

const { Observable } = rxjs;

const notifications$ = new Observable(observer => {
  const interval = setInterval(() => {
    observer.next('Nova Noticia.');
  }, 2000);

  return () => clearInterval(interval);
});

const subscription = notifications$.subscribe(console.log);

setTimeout(() => subscription.unsubscribe(), 8000);

No exemplo de cima, enquanto não há uma desinscrição do Observable, ele ficará emitindo valores.

Como no exemplo do restaurante. A Promise é o menu, ele sempre estará lá, da mesma forma. Enquanto no observable, toda vez que chega alguém novo, o Garçom pode chegar com o Menu, ou com outra informação ao cliente que ele achar relevante.

Recapitulando.

  • Promise são ansiosas, enquanto Observable são preguiçosos.
  • Promise sempre são assíncronas, enquanto Observable pode ser tanto síncronas quanto assíncronas.
  • Promise sempre retornam o mesmo valor, enquanto Observable pode retornar um fluxo de valores, de nenhum a vários.

Nota de rodapé

O Observable, pode ser aprimorado usando outras ferramentas dentro do RxJS, para tornar ele ainda mais poderoso, conseguindo definir fluxos sobre medida.

Nota de tradução

Esse texto é uma adaptação do texto original JavaScript Theory: Promise vs Observable em Inglês no Medium.

Discussion

pic
Editor guide