Promessa vs Observável

Alguém pode explicar a diferença entre Promise e Observable in Angular?

Um exemplo sobre cada um deles seria útil para entender os dois casos. Em que cenário podemos usar cada caso?

Promessa

Um Promise trata de um único evento quando uma operação assíncrona é concluída ou falha.

Nota: Existem bibliotecas Promise por aí que suportam o cancelamento, mas o ES6 Promise não foi feito até agora.

Observável

Um Observable é como um Stream (em vários idiomas) e permite passar zero ou mais events nos quais o callback é chamado para cada evento.

Freqüentemente Observable é preferível ao Promise porque fornece os resources de Promise e muito mais. Com Observable , não importa se você deseja manipular 0, 1 ou vários events. Você pode utilizar a mesma API em cada caso.

Observable também tem a vantagem sobre a Promise de ser cancelável . Se o resultado de uma solicitação HTTP para um servidor ou alguma outra operação assíncrona dispendiosa não for mais necessária, a Subscription de um Observable permite cancelar a assinatura, enquanto uma Promise eventualmente chamará o retorno de sucesso ou falha mesmo quando você não o fizer precisa da notificação ou do resultado que fornece mais.

Observable fornece operadores como map , forEach , reduce , … similar a um array

Também existem operadores poderosos como retry() , ou replay() , … que geralmente são muito úteis.

Promessas:

  • retornar um valor único
  • não cancelável
  • código mais legível com try / catch e async / await

Observables:

  • trabalhar com vários valores ao longo do tempo
  • cancelável
  • apoio mapa, filtro, reduzir e operadores similares
  • usar extensões reativas (RxJS)
  • uma matriz cujos itens chegam assincronamente ao longo do tempo

Promises e Observables nos fornecem abstrações que nos ajudam a lidar com a natureza assíncrona de nossos aplicativos. A diferença entre eles foi apontada claramente por @ Günter e @Relu.

Como um trecho de código vale mais que mil palavras, deixe passar pelo exemplo abaixo para compreendê-las com mais facilidade.

Obrigado @Christoph Burgdorf pelo incrível artigo


Angular usa Observables Rx.js em vez de promises para lidar com HTTP.

Suponha que você esteja criando uma function de pesquisa que mostrará instantaneamente os resultados à medida que você digita. Soa familiar, mas há muitos desafios que acompanham essa tarefa.

  • Não queremos atingir o endpoint do servidor sempre que o usuário pressiona uma tecla, isso deve inundá-lo com uma tempestade de solicitações HTTP . Basicamente, queremos apenas atingi-lo uma vez que o usuário tenha parado de digitar em vez de usar cada tecla.
  • Não acione o ponto de extremidade de pesquisa com os mesmos parâmetros de consulta para solicitações subsequentes.
  • Lidar com respostas fora de ordem. Quando temos várias solicitações em voo ao mesmo tempo, devemos contabilizar os casos em que elas voltam na ordem inesperada. Imagine que primeiro digitamos computador , paramos, um pedido sai, digamos carro , paramos, um pedido é encerrado. Agora temos dois pedidos em andamento. Infelizmente, o pedido que leva os resultados para o computador volta após o pedido que leva os resultados para o carro .

A demo consistirá simplesmente em dois arquivos: app.ts e wikipedia-service.ts . Em um cenário do mundo real, nós provavelmente dividiríamos as coisas ainda mais.


Abaixo está a implementação baseada em Promise que não manipula nenhum dos casos de borda descritos.

wikipedia-service.ts

 import { Injectable } from '@angular/core'; import { URLSearchParams, Jsonp } from '@angular/http'; @Injectable() export class WikipediaService { constructor(private jsonp: Jsonp) {} search (term: string) { var search = new URLSearchParams() search.set('action', 'opensearch'); search.set('search', term); search.set('format', 'json'); return this.jsonp .get('http://en.wikipedia.org/w/api.php?callback=JSONP_CALLBACK', { search }) .toPromise() .then((response) => response.json()[1]); } } 

Estamos injetando o serviço Jsonp para fazer uma solicitação GET contra a API da Wikipedia com um determinado termo de pesquisa. Observe que chamamos para toPromise para obter de uma Observable para uma Promise . Eventualmente acabe com uma Promise> como o tipo de retorno do nosso método de busca.

app.ts

 // check the plnkr for the full list of imports import {...} from '...'; @Component({ selector: 'my-app', template: ` 

Wikipedia Search

  • {{item}}
` }) export class AppComponent { items: Array; constructor(private wikipediaService: WikipediaService) {} search(term) { this.wikipediaService.search(term) .then(items => this.items = items); } }

Não é uma grande surpresa aqui também. Injetamos nosso serviço da WikipediaService e expomos sua funcionalidade por meio de um método de pesquisa ao modelo. O modelo simplesmente se liga a keyup e chama a search(term.value) .

Nós desdobramos o resultado da promise de que o método de pesquisa do WikipediaService retorna e o expõe como uma simples matriz de strings para o template, de modo que possamos fazer *ngFor loop e construir uma lista para nós.

Veja o exemplo da implementação baseada em Promise no Plunker


Onde Observables realmente brilham

Vamos mudar nosso código para não marcanvasr o endpoint com cada keystroke, mas apenas enviar uma requisição quando o usuário parar de digitar por 400 ms

Para revelar esses super poderes, primeiro precisamos obter um Observable que carrega o termo de pesquisa que o usuário digita. Em vez de vincular manualmente ao evento keyup, podemos tirar vantagem da diretiva formControl do Angular. Para usar esta diretiva, primeiro precisamos importar o ReactiveFormsModule para o nosso módulo de aplicativo.

app.ts

 import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { JsonpModule } from '@angular/http'; import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ imports: [BrowserModule, JsonpModule, ReactiveFormsModule] declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule {} 

Uma vez importada, podemos usar o formControl de dentro do nosso template e configurá-lo com o nome “term”.

  

Em nosso componente, criamos uma instância de FormControl de @angular/form e a expomos como um campo sob o termo de nome em nosso componente.

Nos bastidores, o termo expõe automaticamente um Observable como propriedade valueChanges qual podemos nos inscrever. Agora que temos um Observable , superar a input do usuário é tão fácil quanto chamar debounceTime(400) em nosso Observable . Isso retornará um novo Observable que somente emitirá um novo valor quando não houver novos valores para 400ms.

 export class App { items: Array; term = new FormControl(); constructor(private wikipediaService: WikipediaService) { this.term.valueChanges .debounceTime(400) // wait for 400ms pause in events .distinctUntilChanged() // ignore if next search term is same as previous .subscribe(term => this.wikipediaService.search(term).then(items => this.items = items)); } } 

Seria um desperdício de resources enviar outro pedido para um termo de pesquisa para o qual nosso aplicativo já exibe os resultados. Tudo o que precisamos fazer para obter o comportamento desejado é chamar o operador distinctUntilChanged logo após chamarmos debounceTime(400)

Veja o exemplo da implementação Observable no Plunker

Para lidar com respostas fora de ordem, consulte o artigo completo http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

Tanto quanto eu estou usando o Http em Angular, eu concordo que nos casos de uso normal não há muita diferença ao usar Observable over Promise. Nenhuma das vantagens é realmente relevante aqui na prática. Espero que eu possa ver algum caso de uso avançado no futuro 🙂


Saber mais

Promessas e observáveis nos ajudarão a trabalhar com as funcionalidades assíncronas do JavaScript. Eles são muito semelhantes em muitos casos, no entanto, ainda existem algumas diferenças entre os dois também, promises são valores que serão resolvidos de asynchronous como as chamadas http . Por outro lado, os observáveis ​​lidam com a sequência de events asynchronouss . As principais diferenças estão listadas abaixo:

promise:

  • tendo uma linha de tubulação
  • geralmente só usa com retorno de dados asynchronous
  • não é fácil cancelar

observável:

  • são canceláveis
  • são retraíveis por natureza, como tentar novamente e tentar novamente
  • transmitir dados em várias linhas de tubulação
  • ter operações parecidas com uma matriz, como mapear, filtrar, etc.
  • pode ser criado a partir de outras fonts, como events
  • eles são function, que poderia ser inscrito mais tarde

Além disso, criei a imagem gráfica abaixo para mostrar as diferenças visualmente:

Promises and Observables image

Promessas

  1. Definição: Ajuda a executar funções de forma assíncrona e usar seus valores de retorno (ou exceções), mas apenas uma vez quando executadas.
  2. Não preguiçoso
  3. Não cancelável. As duas decisões possíveis são
    • Rejeitar
    • Resolver
  4. Não é possível tentar novamente (as Promessas devem ter access à function original que retornou a promise para ter um recurso de repetição, o que é uma prática ruim)

Observáveis

  1. Definição: Ajuda a executar funções de forma assíncrona e usar seus valores de retorno em uma seqüência contínua ( várias vezes ) quando executadas.
  2. Por padrão, é Preguiçoso, pois emite valores quando o tempo progride.
  3. Tem muito operador que simplifica o esforço de codificação.
  4. Uma nova tentativa do operador pode ser usada para tentar novamente sempre que necessário, também se precisarmos repetir o observável com base em algumas condições que podem ser usadas novamente .

    Nota : Uma lista de operadores junto com seus diagramas interativos está disponível aqui em RxMarbles.com

Há uma desvantagem de Observables ausentes nas respostas. Promessas permitem usar as funções async / wait do ES7. Com eles, você pode escrever um código asynchronous como se fosse uma chamada de function síncrona, para que você não precise mais de callbacks. A única possibilidade de os observáveis ​​fazerem isso é convertê-los em promises. Mas quando você os converte para Promessas, você só pode ter um valor de retorno novamente:

 async function getData(){ const data = await observable.first().toPromise(); //do stuff with 'data' (no callback function needed) } 

Leitura adicional: Como posso ‘aguardar’ em um Rx Observable?

Eu sou um cara de fotos, isso estava faltando em outras respostas:

insira a descrição da imagem aqui

Promessas vs observáveis

promises e Observable ambos estão lidando com a chamada assíncrona apenas. Encontre a imagem acima para a diferença principal.

Mesmo que esta resposta esteja atrasada, eu resumi as diferenças abaixo,

Observável:

  1. Observable é apenas uma function que pega an observer e retorna uma function Observer: an object with next, error.
  2. Observador permite subscribe/unsubscribe a subscribe/unsubscribe stream de dados, emitir o próximo valor para o observador, notify o observador sobre errors e informar o observador sobre a stream completion
  3. O Observer fornece uma function to handle next value , erros e fim do stream (events ui, respostas http, dados com sockets da web).
  4. Trabalha com multiple values longo do tempo
  5. É cancel-able/retry-able e suporta operadores como map,filter,reduce etc.
  6. Criando um Observable pode ser – Observable.create() – retorna Observable que pode invocar methods no – Observer Observable.from() – converte uma matriz ou iterable em – Observable Observable.fromEvent() – converte um evento em Observable – Observable.fromPromise() – converte um Promise em Observable – Observable.range() – retorna uma sequência de números inteiros no intervalo especificado

Promessa :

  1. Uma promise representa uma tarefa que terminará no futuro;

  2. As promises são resolved by a value ;

  3. Promessas são rejeitadas por exceções;

  4. Não cancellable e retorna a single value

  5. Uma promise expõe uma function (then)

    -então retorna uma nova promise ;

    – permite que o attachment seja executado com base no state ;

    – os handlers têm a guaranteed de executar em order attached ;

Acabei de lidar com um problema em que o Promises era a melhor solução, e estou compartilhando aqui para qualquer um que tropeçar nessa questão, caso seja útil (essa era exatamente a resposta que eu estava procurando anteriormente):

Em um projeto Angular2, tenho um serviço que recebe alguns parâmetros e retorna uma lista de valores para preencher menus suspensos em um formulário. Quando o componente de formulário é inicializado, preciso chamar o mesmo serviço várias vezes com parâmetros diferentes para definir vários menus suspensos diferentes, no entanto, se eu simplesmente enfileirar todas as variables ​​para chamar o serviço, apenas o último será bem-sucedido e o restante Fora. A busca de serviço do database pode manipular apenas uma solicitação por vez.

A única maneira de preencher com êxito todas as variables ​​do menu suspenso era chamar o serviço de forma a impedir que uma nova solicitação fosse processada até que a última solicitação fosse concluída, e o mecanismo Promise / .then solucionou bem o problema.

  fetchValueList(listCode): Promise { return this.dataSvc.getValueList(listCode, this.stateSvc.currentContext, this.stateSvc.currentLanguageCode) .map(response => response.json()) .toPromise(); } initializeDropDowns() { this.fetchValueList('First-Val-List') .then(data => { this.firstValList = data; return this.fetchValueList('Second-Val-List') }).then(data => { this.secondValList = data; return this.fetchValueList('Third-Val-List') }).then(data => { this.thirdValList = data; }) } 

Eu defini as funções no componente e, em seguida, chamei initializeDropDowns () em ngOnInit.

A function fetchValueList retorna um Promise, portanto, a primeira chamada passa pelo primeiro listCode e, quando o Promise é resolvido, o valor de retorno está na variável de dados no bloco .then, onde podemos atribuí-lo à variável this.firstValList. Como a function retornou dados, nós sabemos que o serviço terminou e é seguro chamar novamente com o segundo listCode, o valor de retorno está na variável de dados no próximo bloco e nós o atribuímos à variável this.secondValList.

Podemos encadear isso quantas vezes forem necessárias para preencher todas as variables, e no último bloco de código simplesmente omitimos a declaração de retorno e o bloco termina.

Este é um caso de uso muito específico em que temos um único serviço que precisa ser chamado várias vezes à medida que o componente é inicializado e onde o serviço precisa concluir sua busca e retornar um valor antes de poder ser chamado novamente, mas neste caso, o método Promise / .then foi ideal.

Acredito que todas as outras respostas devem esclarecer suas dúvidas. No entanto, eu só queria acrescentar que observables são baseados em functional programming, e eu acho muito útil as funções que vêm com ele como map, flatmap, reduce, zip. A consistência que a Web alcança, especialmente quando depende de solicitações da API, é uma melhoria brutal.

Eu recomendo fortemente esta documentação , já que é a documentação oficial do reactiveX e eu acho que é a mais clara lá fora.

Se você quiser entrar em observables eu sugeriria este post de 3 partes: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/

Embora seja para o RxJava, os conceitos são os mesmos e são muito bem explicados. Na documentação do reactiveX você tem as equivalências para cada function. Você deve procurar por RxJS.

Espero que isso ajude, tentei contribuir aqui. 🙂

Observables vs promises

Promessas e observáveis , ambos nos fornecem uma maneira simples que nos ajudam a enfrentar com a tentativa de natureza assíncrona de nossas aplicações. No entanto, existem diferenças importantes entre os dois:

  • Observables pode definir os aspectos de configuração e desassembly do comportamento asynchronous.
  • Observáveis são canceláveis.
  • Além disso, observáveis podem ser repetidos usando um dos operadores de repetição fornecidos pela API, como repetir e tentar novamente. Por outro lado, o Promises exige que o chamador tenha access à function original que retornou a promise para ter um recurso de repetição.

As promises realmente reforçam essa semântica. Você pode criar um Promise, que resolve com algum valor:

  const numberPromise = new Promise((resolve) => { resolve(5); }); numberPromise.then(value => console.log(value)); // will simply print 5 

Mas tentar resolver o Promise novamente com outro valor falhará. A promise sempre é resolvida com o primeiro valor passado para a function de resolução e ignora outras chamadas para ela:

  const numberPromise = new Promise((resolve) => { resolve(5); resolve(10); }); numberPromise.then(value => console.log(value)); // still prints only 5 

Pelo contrário, os observáveis ​​permitem que você resolva (ou, como dizemos, “emita”) vários valores. Aqui está como ficaria:

  const numberObservable = new Observable((observer) => { observer.next(5); observer.next(10); }); numberObservable.subscribe(value => console.log(value)); // prints 5 and 10 

Note como é similar a syntax – trocamos Promise para Observable, substituímos resolve function por observer.next call e em vez de usarmos o subscribe, que se comporta de maneira muito similar.

Promessa:

  • Forneça um único valor futuro;
  • Não preguiçoso;
  • Não cancelável;

Observável:

  • Emite vários valores ao longo do tempo;
  • Preguiçoso;
  • Cancelável;
  • Suporta mapear, filtrar, reduzir e operadores similares

Você pode usar promises em vez de observáveis ​​ao chamar HTTP em Angular, se desejar.

Promise – Forneça um único valor futuro. Não preguiçoso . Não cancelável. Ele irá rejeitar ou resolver.

Observável – Forneça vários valores futuros. Preguiçoso Cancelável. Ele fornece outros methods ao vivo mapa, filtro, reduzir.

Visão geral:

  • Promessas e Observáveis ​​nos ajudam a lidar com operações assíncronas. Eles podem chamar certos retornos de chamada quando essas operações assíncronas são feitas.
  • Um Promise só pode manipular um evento, Observables são para streams de events ao longo do tempo
  • As promises não podem ser canceladas quando estiverem pendentes
  • Os dados observáveis ​​emitidos podem ser transformados usando operadores

Você sempre pode usar um observável para lidar com comportamento asynchronous, já que um observável tem a funcionalidade de uma promise. No entanto, às vezes, essa funcionalidade extra que os Observables oferecem não é necessária. Em seguida, seria uma sobrecarga extra para importar uma biblioteca para usá-las.

Quando usar promises:

Use promises quando você tiver uma única operação assíncrona da qual deseja processar o resultado. Por exemplo:

 var promise = new Promise((resolve, reject) => { // do something once, possibly async // code inside the Promise constructor callback is getting executed synchronously if (/* everything turned out fine */) { resolve("Stuff worked!"); } else { reject(Error("It broke")); } }); //after the promise is resolved or rejected we can call .then or .catch method on it promise.then((val) => console.log(val)) // logs the resolve argument .catch((val) => console.log(val)); // logs the reject argument 

Portanto, uma promise executa algum código onde ela é resolvida ou rejeitada. Se resolver ou rejeitar é chamado, a promise passa de um estado pendente para um estado resolvido ou rejeitado . Quando o estado da promise é resolvido, o método then() é chamado. Quando o estado da promise é rejeitado, o método catch() é chamado.

Quando usar Observables:

Use Observables quando houver um stream ao longo do tempo que você precisa manipular. No próprio Observable é especificado quando o próximo evento aconteceu, quando ocorre um erro ou quando o Observable é concluído. Então podemos nos inscrever neste observable, que o ativa e nesta assinatura podemos passar em 3 callbacks (nem sempre tem que passar em todos). Um retorno de chamada a ser executado para sucessão, um retorno de chamada para erro e um retorno de chamada para conclusão. Por exemplo:

 const observable = Rx.Observable.create(observer => { // create a single value and complete observer.onNext(1); observer.onCompleted(); }); source.subscribe( x => console.log('onNext: %s', x), // success callback e => console.log('onError: %s', e), // error callback () => console.log('onCompleted') // completion callback ); // first we log: onNext: 1 // then we log: onCompleted 

Ao criar um observável, ele requer uma function de retorno de chamada que fornece um observador como argumento. Neste observador, você pode chamar onCompleted , onCompleted , onError . Então, quando o Observable estiver inscrito, ele chamará os retornos de chamada correspondentes passados ​​para a assinatura.

Já existem muitas respostas sobre esse tópico, então eu não adicionaria uma redundante.

Mas para alguém que acabou de começar a aprender Observable / Angular e se pergunta qual usar para comparar com Promise , eu recomendo que você mantenha tudo Observable e converta todas as Promessas existentes em seu projeto para Observable.

Simplesmente porque o próprio framework Angular e sua comunidade estão usando o Observable. Por isso, seria benéfico quando você integra serviços de estrutura ou módulos de terceiros e encadeia tudo juntos.

Explique na referência de chamadas HTTP angulares para Api remoto: promises é usado para manter o estado de chamadas assíncronas. um dos dados é obtido a partir de Api remoto e mostrar em vista

e em Observable vêm de padrões observáveis ​​e são introduzidos por Rxjs quando ele oferece facilidade para atualizar dados várias vezes ao longo do stream como dados observáveis.