Qual é a diferença entre Promessas e Observáveis?

1397

Qual é a diferença entre Promisee Observableem Angular?

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

Rohit
fonte
23
Eu sugiro que você leia este post; Angular2 promessa vs observável
erolkaya84
4
em termos mais simples, angular-2-training-book.rangle.io/handout/observables/…
Pardeep Jain
3
Para qualquer pessoa que esteja lendo estas perguntas e respostas - como alguém envolvido em ambos os mundos, de um mantenedor, palestrante e usuário de longa data PoV, recomendo que você leia os documentos oficiais do RxJS e a documentação do MDN sobre promessas. Pessoalmente, acho as respostas aqui totalmente enganosas e incorretas e acredito que elas são, embora com boas intenções de pessoas que tentam ajudar, muito prejudiciais.
Benjamin Gruenbaum
1
Eu sugiro que você leia este documento oficial angular angular.io/guide/comparing-observables
fgul
E é por isso que os links são considerados inaceitáveis ​​como respostas.
Dave

Respostas:

1551

Promessa

A Promiselida com um único evento quando uma operação assíncrona é concluída ou falha.

Nota: Existem Promisebibliotecas por aí que oferecem suporte ao cancelamento, mas o ES6 Promiseainda não.

Observável

An Observableé como um Stream(em muitos idiomas) e permite passar zero ou mais eventos nos quais o retorno de chamada é chamado para cada evento.

Geralmente, Observableé preferível ao Promiseinvés de fornecer os recursos Promisee muito mais. Com Observableisso, não importa se você deseja lidar com 0, 1 ou vários eventos. Você pode utilizar a mesma API em cada caso.

Observabletambém tem a vantagem Promisede ser cancelável . Se o resultado de uma solicitação HTTP para um servidor ou alguma outra operação assíncrona cara não for mais necessário, o Subscriptionde an Observablepermitirá cancelar a assinatura, enquanto um Promiseeventualmente chamará o retorno de retorno bem-sucedido ou com falha, mesmo quando você não precisa da notificação ou o resultado que ele fornece mais.

Observável fornece operadores como map, forEach, reduce, ... semelhantes a um array

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

Günter Zöchbauer
fonte
180
Portanto, existe um bom motivo para usar o Promise em vez de Observable no caso de retorno de chamada único ou o Observables também deve ser usado lá, pois eles também podem funcionar dessa maneira? Basicamente, é uma boa prática "Observar todas as coisas" ou a Promise ainda tem seu lugar?
21716 Josh Werts
75
Se você deseja usar o estilo reativo, use observáveis ​​em qualquer lugar. Se você tiver apenas observáveis, poderá compor com facilidade. Se você misturá-los, não está mais tão limpo. Se você não se importa com o estilo reativo, pode usar a promessa para eventos únicos em que não se preocupa com cancelável e observável para fluxos de eventos.
Günter Zöchbauer
35
@ GünterZöchbauer Hey - Não tenho argumentos contra o Observables ou a programação funcional. Estou simplesmente afirmando que acredito que as pessoas que se deparam com o Observables principalmente via http no NG2 não têm nenhum motivo real para usar o Observables ao invés de promessas para fazer as ligações. Eles não perdem nada prático usando promessas. Os operadores de devolução e nova tentativa são irrelevantes - você pode devolver com ng-debounce e, se uma chamada falhar, geralmente há um problema com o código. O único momento em que precisei trabalhar com novas tentativas de chamadas foi consultando APIs instáveis ​​de terceiros para HVT.
VSO 30/01
92
Mas, por favor, não esqueça que Promise, junto com async/ awaittorna seu código plano novamente! Na maioria das situações, e em projetos que não lidam com ciência de foguetes, não há necessidade de escrever essas funções aninhadas horríveis com cadeias de métodos desnecessariamente complicadas. Você pode usar async/ awaittoday com transpilers, como TypeScripte escrever código plano legível por humanos real sem qualquer um dos rxjspadrões. Você provavelmente ainda precisará, rxjsalgumas vezes, em situações selecionadas, porque realmente tem muitas coisas a oferecer.
Evilkos 02/07
15
Essa resposta é enganosa, um observável não é como um fluxo, é como uma função que retorna um fluxo .
Benjamin Gruenbaum
335

Ambos Promisese Observablesnos 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, vamos seguir o exemplo abaixo para entendê-las mais facilmente.

Obrigado @Christoph Burgdorf pelo artigo incrível


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

Suponha que você esteja criando uma função de pesquisa que mostre resultados instantaneamente enquanto você digita. Parece familiar, mas há muitos desafios que acompanham essa tarefa.

  • Não queremos atingir o ponto final do servidor toda vez que o usuário pressionar uma tecla, ela deve inundá-los com uma tempestade de HTTPsolicitações. Basicamente, queremos apenas pressioná-lo quando o usuário parar de digitar em vez de pressionar cada tecla.
  • Não atinja 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 andamento ao mesmo tempo, devemos considerar os casos em que elas retornam em ordem inesperada. Imagine que primeiro digitamos computador , paramos, uma solicitação sai, digitamos carro , paramos, uma solicitação sai. Agora, temos dois pedidos em voo. Infelizmente, a solicitação que carrega os resultados para o computador volta após a solicitação que carrega os resultados para o carro .

A demonstração consiste simplesmente em dois arquivos: app.tse wikipedia-service.ts. Em um cenário do mundo real, provavelmente dividiríamos ainda mais as coisas.


Abaixo está a implementação baseada em promessa que não lida com nenhum dos casos extremos 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 Jsonpserviço para fazer uma GETsolicitação na API da Wikipedia com um determinado termo de pesquisa. Observe que chamamos toPromisepara passar de um Observable<Response>para um Promise<Response>. Eventualmente, acabam com a Promise<Array<string>>como o tipo de retorno do nosso método de pesquisa.

app.ts

// check the plnkr for the full list of imports
import {...} from '...';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Wikipedia Search</h2>
      <input #term type="text" (keyup)="search(term.value)">
      <ul>
        <li *ngFor="let item of items">{{item}}</li>
      </ul>
    </div>
  `
})
export class AppComponent {
  items: Array<string>;

  constructor(private wikipediaService: WikipediaService) {}

  search(term) {
    this.wikipediaService.search(term)
                         .then(items => this.items = items);
  }
}

Não é muita surpresa aqui também. Injetamos nossa WikipediaServicee expomos sua funcionalidade por meio de um método de pesquisa ao modelo. O modelo simplesmente liga-se a keyup e chamadas search(term.value).

Desembrulhamos o resultado da Promessa de que o método de pesquisa do WikipediaService retorna e o expomos como uma Matriz simples de seqüências de caracteres para o modelo, para que possamos fazer um *ngForloop e criar uma lista para nós.

Veja o exemplo de implementação baseada em promessa no Plunker


Onde os Observáveis realmente brilham

Vamos alterar nosso código para não martelar o ponto final a cada pressionamento de tecla, mas enviar apenas uma solicitação quando o usuário parar de digitar por 400 ms

Para revelar essas superpotências, primeiro precisamos obter um Observable<string>que carregue o termo de pesquisa digitado pelo usuário. Em vez de vincular manualmente ao evento keyup, podemos tirar proveito da formControldiretiva da Angular . Para usar essa diretiva, primeiro precisamos importar o arquivo para o ReactiveFormsModulenosso 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 importados, podemos usar o formControl de dentro do nosso modelo e defini-lo com o nome "termo".

<input type="text" [formControl]="term"/>

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

Nos bastidores, o termo expõe automaticamente uma Observable<string>propriedade as valueChangesque podemos assinar. Agora que temos uma Observable<string>, superar a entrada do usuário é tão fácil quanto ligar debounceTime(400)para a nossa Observable. Isso retornará um novo Observable<string>que somente emitirá um novo valor quando não houver novos valores por 400ms.

export class App {
  items: Array<string>;
  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 recursos enviar outra solicitação de um termo de pesquisa para o qual nosso aplicativo já mostra os resultados. Tudo o que precisamos fazer para alcançar o comportamento desejado é ligar para o distinctUntilChangedoperador logo depois que ligamosdebounceTime(400)

Veja o exemplo de implementação observável 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

Quanto ao uso do Http no Angular, concordo que nos casos de uso normais não há muita diferença ao usar o Observable over Promise. Nenhuma das vantagens é realmente relevante aqui na prática. Espero ver alguns casos de uso avançados no futuro :)


Saber mais

trungk18
fonte
31
Eu não compro completamente a decisão de transformar o serviço Http em Observable. Toda explicação que ouço baseia-se no mesmo exemplo: A pesquisa por termo. Mas esse é sobre como lidar com eventos do navegador. Gostaria de saber qual é a vantagem de aplicá-lo ao lidar com solicitações http assíncronas.
Alex Pollan
1
A decisão foi acidental para evitar padrões mistos?
Alex-Pollan #
6
@AlexPollan, na verdade, há uma boa explicação para os benefícios do serviço http retornando um observável neste podcast com Ben Lesh: devchat.tv/js-jabber/… . Por fim, o principal benefício é que você pode cancelar um observável e um caso de uso para isso descrito no link acima - embora um pouco artificial - é que se você chamar várias APIs e se importar apenas com a primeira resposta, não importa qual das APIs que você ligou primeiro, você pode cancelar as solicitações para as outras.
Nikolasleblanc
2
@nikolasleblanc, tenho certeza que você pode usar $ q.race () para isso?
Jameslouiz
2
@AlexPollan, A vantagem é que um serviço HTTP baseado em Observable facilita o cancelamento de solicitações HTTP em andamento. A condição de corrida na resposta de trungk18 pode ser resolvida simplesmente cancelando a inscrição no HTTP observável antes de fazer uma solicitação subsequente. O RXJS switchMap pode ser usado para solicitações HTTP acionadas por outro observável (por exemplo, valueChanges). Para observáveis ​​HTTP independentes, é possível cancelar a assinatura e reinscrever-se manualmente.
Stevethemacguy 16/01
236

Ambas as promessas e observáveis nos ajudará a trabalhar com as funcionalidades assíncronas em JavaScript. Eles são muito semelhantes em muitos casos, no entanto, ainda existem algumas diferenças entre os dois, promessas são valores que serão resolvidos de asynchronousmaneiras como chamadas http . Por outro lado, os observáveis ​​lidam com uma sequência de eventos assíncronos . As principais diferenças entre eles estão listadas abaixo:

promessa:

  • tendo um pipeline
  • geralmente use apenas com retorno de dados assíncrono
  • não é fácil cancelar

observável:

  • são canceláveis
  • são recuperáveis ​​por natureza, como nova tentativa e nova tentativa.
  • transmitir dados em vários pipelines
  • tendo operações tipo array como map, filter etc
  • pode ser criado a partir de outras fontes, como eventos
  • são funções, que poderão ser subscritas posteriormente

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

Imagem de Promessas e Observáveis

Alireza
fonte
4
promessa "não é fácil cancelar", é possível cancelá-los?
precisa
10
sim, existe uma maneira de cancelá-los também ... algumas pessoas usam bibliotecas bluebird ou de terceiros ... também usando a biblioteca Q no Angular existem maneiras de cancelá-lo ... mas como eu disse não é muito útil
Alireza
Ter um oleoduto às vezes tem vantagens, ex. em APP_INITIALIZER, se você tiver vários pipeline, ele nunca poderá terminar algumas vezes ou terminar várias vezes.
Windmaomao 18/05/19
6
cancelar a Promiseé a maneira errada de pensar sobre como promete. É de Promiseresponsabilidade apenas lidar com sucesso ou falha de maneira assíncrona compatível. Se você deseja cancelar uma solicitação http, cancela a solicitação, não a promessa, e faz com que o resultado do cancelamento cumpra ou rejeite a Promessa. jsfiddle.net/greggman/ea0yhd4p
gman
2
@ gman Exatamente. A promessa simplesmente representa algum valor futuro . Ele não representam a operação que gera o valor . Você não pode cancelar um valor. Você não pode tentar um valor novamente. É apenas um valor. Pode ou não estar presente ainda, e talvez nunca exista porque ocorreu uma exceção, mas é isso.
Yona Appletree
75

Promessas

  1. Definição: Ajuda a executar funções de forma assíncrona e a usar seus valores de retorno (ou exceções), mas apenas uma vez quando executadas.
  2. Não preguiçoso
  3. Não cancelável (existem bibliotecas Promise disponíveis no mercado que oferecem suporte ao cancelamento, mas o ES6 Promise não oferece até o momento). As duas decisões possíveis são
    • Rejeitar
    • Resolver
  4. Não é possível tentar novamente (as promessas devem ter acesso à função original que retornou a promessa de 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 a usar seus valores de retorno em uma sequência contínua ( várias vezes ) quando executadas.
  2. Por padrão, é Preguiçoso, pois emite valores quando o tempo avança.
  3. Tem muitos operadores que simplificam o esforço de codificação.
  4. Uma nova tentativa do operador pode ser usada para repetir sempre que necessário, também se precisarmos repetir o observável com base em algumas condições . podem ser usados.

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

Aravind
fonte
67

Há uma desvantagem do Observables ausente nas respostas. As promessas permitem usar as funções de assíncrona / espera do ES7. Com eles, você pode escrever código assíncrono como se fosse uma chamada de função síncrona, para que você não precise mais de retornos de chamada. A única possibilidade dos Observables fazerem isso é convertê-los em Promessas. Mas quando você as converte em Promessas, você pode ter apenas 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?

besserwisser
fonte
21
Também surpreendeu por que ninguém apontou esse privilégio matador de promessas - simplicidade e transparência graças ao async / waitit. Mudei para o Promises apenas pela capacidade de escrever código simples. A lógica comercial simples e o código de interação da interface do usuário não devem parecer ciência de foguetes e devem ser poluídos pelo inferno aninhado de extensões reativas. Além disso, o assíncrono / espera não é apenas no futuro, você pode usá-lo em aplicativos de produção pública agora usando transpilers. Eu uso o TypeScript 2.3 e é incrível, como uma linguagem real.
Evilkos 02/07
Bom, mas pensando de forma reativa e todos com os RxOperators talvez esta não é uma característica do assassino
JorgeTovar
37

Promessas e Observáveis ​​tratam apenas da chamada assíncrona.

Aqui estão as diferenças entre eles:

Observável

  1. Emite vários valores ao longo de um período de tempo
  2. Não é chamado até assinarmos o Observable
  3. Pode ser cancelado usando o método unsubscribe ()
  4. Fornece o mapa, paraCada, filtra, reduz, tenta e tenta novamente

Promessa

  1. Emite apenas um único valor de cada vez

  2. Chama os serviços sem .then e .catch

  3. Não pode ser cancelado

  4. Não fornece nenhum operador

sudheer nunna
fonte
2
O que exatamente você quer dizer com emite promessa única de valor único, enquanto emite observáveis múltipla
Abel
2
Uma promessa não emite nenhum valor - uma promessa é um valor ao longo do tempo. Uma promessa é multitarefa que valoriza para vários assinantes - depois de cumprida a promessa, você já tem um valor. Um observável é como uma função , ao se inscrever, ele invoca a ação.
Benjamin Gruenbaum
1
@BenjaminGruenbaum Ainda não entendi a média de vários assinantes, você pode fornecer um link ou exemplo. Obrigado
Deepak Patidar
2
observable1.subscribe (subscriber1), observable1.subscribe (subscriber2) - isso chama a função várias vezes.
Benjamin Gruenbaum
2
Por favor edite seu post e mostrar o texto real em vez de screenshots. Outros não podem copiar e colar suas imagens e também não podem ajudá-lo a corrigir os muitos erros gramaticais. Veja aqui para detalhes. Obrigado.
Pang
26

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

Observável:

  1. Observável é apenas um functionque pega an observere retorna um function Observer: an object with next, error.
  2. O observador permite ao subscribe/unsubscribeseu fluxo de dados, emitir o próximo valor para o observador, notifyo observador errorse informar o observador sobre ostream completion
  3. O Observer fornece a function to handle next value, erros e fim do fluxo (eventos da interface do usuário, respostas http, dados com soquetes da web).
  4. Funciona com multiple valueso tempo
  5. É cancel-able/retry-ablee suporta operadores como map,filter,reduceetc.
  6. Criar um Observable pode ser - Observable.create()- retorna Observable que pode chamar métodos em - Observer Observable.from()- converte uma matriz ou iterável em - Observable Observable.fromEvent()- converte um evento em Observable - Observable.fromPromise()- converte uma Promessa em Observable - Observable.range()- retorna uma sequência de números inteiros no intervalo especificado

Promessa :

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

  2. Promessas se tornam resolved by a value;

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

  4. Não cancellablee retornaa single value

  5. Uma promessa expõe uma função (then)

    -Então retorna um novo promise;

    - permite que o attachmentque seja executado com base em state ;

    - handlersdevem guaranteedexecutar dentro order attached;

Sajeetharan
fonte
20

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

Em um projeto Angular2, tenho um serviço que usa alguns parâmetros e retorna uma lista de valores para preencher os menus suspensos em um formulário. Quando o componente do 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 variáveis ​​para chamar o serviço, apenas o último é bem-sucedido e o erro restante Fora. A busca do serviço no banco de dados pode lidar apenas com uma solicitação por vez.

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

  fetchValueList(listCode): Promise<any> {
      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 função fetchValueList retorna uma Promise; portanto, a primeira chamada passa o primeiro listCode e, quando a Promise é resolvida, o valor de retorno está na variável de dados no bloco .then, onde podemos atribuí-lo à variável this.firstValList. Como a função retornou dados, sabemos que o serviço foi concluído e é seguro chamar novamente com o segundo listCode, o valor de retorno está na variável de dados no próximo bloco .then e o atribuímos à variável this.secondValList.

Podemos encadear isso quantas vezes for necessário para preencher todas as variáveis ​​e, no último bloco de código, simplesmente omitimos a instrução de retorno e o bloco termina.

Esse é um caso de uso muito específico, em que temos um único serviço que precisa ser chamado várias vezes quando o componente é inicializado e em que 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.

Stephen R. Smith
fonte
3
Isso certamente também é possível com observáveis ​​(de ordem superior). Você poderia, por exemplo, usar scan()para criar um fluxo de observáveis ​​seqüenciais. No entanto, sua abordagem talvez seja mais explícita e mais fácil de entender.
Lex82 27/04
1
Você pode substituir "then" por "switchMap" e fazer exatamente a mesma coisa com observáveis.
Dr. C. Hilário
1
O problema com o switchMap, como eu o entendo, é que ele iniciará todas as solicitações em paralelo e esperará até que todas retornem, retornando os valores para a função de chamada, enquanto na minha situação, eu tenho um único servidor que não posso ligar várias vezes em paralelo (como o servidor descartará solicitações inacabadas quando novas forem recebidas), tive que garantir que cada chamada para o serviço de banco de dados fosse concluída antes de iniciar uma nova chamada, e o Promise / parecia ser o melhor e talvez a única maneira de resolver isso.
Stephen R. Smith
1
Por que você não usou o mergeMap encadeado? Até onde eu entendi o seu código, este é bem simples e faz o trabalho tão bem quanto o seu exemplo. @ StephenR.Smith
Ore
1
@ Você pode adicionar um exemplo de código que resolve o mesmo problema que outra resposta? Seria uma boa referência e pode ser uma boa oportunidade de refatoração no futuro. O requisito é que qualquer código que não possa chamar o serviço de back-end em paralelo, ele precise ligar, aguardar o valor de retorno e ligar novamente.
Stephen R. Smith
20

Acredito que todas as outras respostas devem esclarecer suas dúvidas. No entanto, eu só queria acrescentar que os observáveis ​​são baseados em programação funcional e acho muito úteis as funções que o acompanham, como map, flatmap, reduzir, zip. A consistência que a Web obtém, especialmente quando depende de solicitações de API, é uma melhoria brutal.

Eu recomendo fortemente esta documentação , pois é a documentação oficial do reactiveX e acho que é a mais clara existente.

Se você quiser entrar no observável, sugiro este post em três partes: http://blog.danlew.net/2014/09/09/15/grokking-rxjava-part-1/

Embora seja destinado ao 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 função. Você deve procurar pelo RxJS.

Marc Pérez
fonte
18

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;
  • Oferece suporte a operadores de mapas, filtros, reduções e similares

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

Iosua Sipos
fonte
16

Visão geral:

  • Promessas e Observáveis ​​nos ajudam a lidar com operações assíncronas. Eles podem chamar determinados retornos de chamada quando essas operações assíncronas são concluídas.
  • Uma promessa pode lidar apenas com um evento; os observáveis ​​são para fluxos de eventos ao longo do tempo
  • As promessas 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 assíncrono, pois um observável tem todas as funcionalidades que uma promessa oferece (+ extra). No entanto, às vezes essa funcionalidade extra oferecida pelo Observables não é necessária. Seria uma sobrecarga extra importar uma biblioteca para usá-los.

Quando usar o Promises:

Use promessas quando 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 promessa executa algum código em que resolve ou rejeita. Se resolver ou rejeitar é chamado, a promessa passa de um estado pendente para um estado resolvido ou rejeitado . Quando o estado da promessa é resolvido, o then()método é chamado. Quando o estado da promessa é rejeitado, ocatch() método é chamado.

Quando usar Observables:

Use Observables quando houver um fluxo (de dados) ao longo do tempo que você precise manipular. Um fluxo é uma sequência de elementos de dados que estão sendo disponibilizados ao longo do tempo . Exemplos de fluxos são:

  1. Eventos do usuário, por exemplo, clique ou eventos de digitação. O usuário gera eventos (dados) ao longo do tempo.
  2. Websockets, depois que o cliente faz uma conexão WebSocket com o servidor, ele envia dados ao longo do tempo.

No próprio Observable é especificado quando o próximo evento ocorreu, quando ocorre um erro ou quando o Observable é concluído . Em seguida, podemos assinar esse observável, que o ativa e, nessa assinatura, podemos transmitir três retornos de chamada (nem sempre é necessário transmitir todos). Um retorno de chamada a ser executado para obter sucesso, um retorno de 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, é necessária uma função de retorno de chamada que forneça um observador como argumento. Nesta observador, então você pode chamar onNext, onCompleted, onError. Então, quando o Observable estiver inscrito, ele chamará os retornos de chamada correspondentes passados ​​para a assinatura.

Willem van der Veen
fonte
9

Promessa - Forneça um único valor futuro. Não preguiçoso . Não pode ser cancelado. Ele rejeitará ou resolverá.

Observável - Forneça vários valores futuros. Preguiçoso. Cancelável. Ele fornece outros métodos de mapa ao vivo, filtro, redução.

Gajender Singh
fonte
8

Promessa versus similaridade observável primeiro

  1. Ambos usados ​​para manipular código assíncrono.
  2. Por favor, procure um exemplo de promessa. O construtor Promise passa uma função de referência de resolução que será chamada quando for chamada com algum valor após a conclusão de alguma tarefa assíncrona.

const promise = new Promise(resolve => {
  setTimeout(() => {
    resolve("Hello from a Promise!");
  }, 2000);
});

promise.then(value => console.log(value));

  1. Exemplo observável agora. Aqui também passamos uma função para observable, um observador para lidar com a tarefa assíncrona. Ao contrário da determinação na promessa, ele possui o método a seguir e se inscreve no lugar dele.

  2. Então, ambos lidam com tarefas assíncronas. Agora vamos ver a diferença.


const observable = new Observable(observer => {
  setTimeout(() => {
    observer.next('Hello from a Observable!');
  }, 2000);
});

observable.subscribe(value => console.log(value));

Promessa vs Diferença observável

Promessa

  1. Ele resolve ou rejeita um único valor e pode manipular uma tarefa assíncrona de valor único por vez.
  2. Uma promessa, uma vez resolvida o valor assíncrono que ela completa, não pode mais ser usada. Ela é usada apenas uma vez e aqui fica aquém.
  3. Não cancelável
  4. Não há suporte ao rxjs para operadores.

Observável

  1. capacidade de emitir vários valores assíncronos.
  2. Usado para manipular o fluxo de eventos ou valores. Considere que você possui uma variedade de tarefas ou valores e deseja que toda vez que o valor for inserido, ele seja tratado automaticamente. Sempre que você insere um valor nessa matriz, todos os seus assinantes receberão o valor mais recente automaticamente.
  3. Observáveis ​​são úteis para observar alterações de entrada, intervalo repetido, valores de transmissão para todos os componentes filhos, notificações push de soquete da Web etc.
  4. Pode ser cancelado usando o método de cancelamento de inscrição a qualquer momento.
  5. Mais uma última parte promissora que oferece suporte a operadores rxjs. Você tem muitos operadores de tubulação majoritariamente mapeados, filtrados, switchMap, combineLatest etc. para transformar dados observáveis ​​antes de assinar.

insira a descrição da imagem aqui


ramesh sharma
fonte
6

Promessas e Observáveis ​​nos ajudam a lidar com operações assíncronas. Eles podem chamar determinados retornos de chamada quando essas operações assíncronas são concluídas.

Angular usa Observables, que é do RxJS, em vez de promessas para lidar com HTTP

Below are some important differences in promises & Observables.

diferença entre promessas e observáveis

Srikrushna
fonte
1
Os dados tabulados parece incorreto, o título deve ser trocado
Derrick.X
1
Por favor editar o seu post e mostrar o conteúdo real como texto em vez de imagens. Outros não podem copiar e colar de suas imagens. Veja aqui para detalhes. Obrigado.
Pang
6

Uma promessa emite um único evento quando uma atividade assíncrona termina ou falha.

Um Observable é como um Stream (em vários idiomas) e permite passar pelo menos zero ou mais eventos nos quais o retorno de chamada é necessário para cada evento.

O Frequently Observable é preferido sobre o Promise, pois fornece os destaques do Promise e muito mais. Com Observable, não importa se você precisa lidar com 0, 1 ou vários eventos. Você pode usar a API semelhante para cada caso.

Promessa: promessa emite um valor único

Por exemplo:

const numberPromise = new Promise((resolve) => {
    resolve(5);
    resolve(10);
});

numberPromise.then(value => console.log(value));
// still prints only 5

Observável: emite vários valores ao longo de um período de tempo

Por exemplo:

  const numberObservable = new Observable((observer) => {
        observer.next(5);
        observer.next(10);
    });

numberObservable.subscribe(value => console.log(value));
// prints 5 and 10

podemos pensar em um observável como um fluxo que emite vários valores ao longo de um período de tempo e a mesma função de retorno de chamada é chamada para cada item emitido; portanto, com um observável, podemos usar a mesma API para manipular dados assíncronos. se esses dados são transmitidos como um valor único ou vários valores ao longo de um período de tempo.

Promessa:

  • Uma promessa não é preguiçosa
  • Uma promessa não pode ser cancelada

Observável:

  • Observável é preguiçoso. O "Observável" é lento. Não é chamado até que estejamos inscritos.
  • Um Observable pode ser cancelado usando o método unsubscribe ()
  • Além disso, o Observable fornece muitos operadores poderosos, como mapa, busca, filtro, redução, nova tentativa, nova tentativa, etc.

Promessas Angulares vs Observáveis

DeC
fonte
5

Promise emite um único valor, enquanto Observable emite vários valores. Portanto, ao lidar com uma solicitação HTTP, o Promise pode gerenciar uma única resposta para a mesma solicitação, mas e se houver várias respostas para a mesma solicitação, precisamos usar Observable. Sim, o Observable pode lidar com várias respostas para a mesma solicitação.

Promessa

const promise = new Promise((data) =>
{ data(1);
  data(2);
  data(3); })
.then(element => console.log(‘Promise ‘ + element));

Resultado

Promise 1

Observável

const observable = new Observable((data) => {
data.next(1);
data.next(2);
data.next(3);
}).subscribe(element => console.log('Observable ' + element));

Resultado

Observable 1
Observable 2
Observable 3
yogesh waghmare
fonte
3

Abaixo estão algumas diferenças importantes nas promessas e Observáveis.

Promessa

  • Emite apenas um único valor
  • Não cancelável
  • Não compartilhável
  • Sempre assíncrono

Observável

  • Emite vários valores
  • Executa apenas quando é chamado ou alguém está se inscrevendo
  • Pode ser cancelável
  • Pode ser compartilhado e assinado esse valor compartilhado por vários assinantes. E todos os assinantes serão executados em um único ponto no tempo.
  • possivelmente assíncrono

Para um melhor entendimento, consulte https://stackblitz.com/edit/observable-vs-promises

Bikram
fonte
3

Vejo muitas pessoas usando o argumento de que Observable é "cancelável", mas é bastante trivial tornar a Promise "cancelável"

function cancellablePromise(body) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res; reject = rej;
    body(resolve, reject)
  })
  promise.resolve = resolve;
  promise.reject = reject;
  return promise
}

// Example 1: Reject a promise prematurely
const p1 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('10', 100))
})

p1.then(value => alert(value)).catch(err => console.error(err))
p1.reject(new Error('denied')) // expect an error in the console

// Example: Resolve a promise prematurely
const p2 = cancellablePromise((resolve, reject) => {
  setTimeout(() => resolve('blop'), 100)
})

p2.then(value => alert(value)).catch(err => console.error(err))
p2.resolve(200) // expect an alert with 200

Batiste Bieler
fonte
2

Resposta curta :

Observável é melhor , tem todos os recursos do Promises , além de recursos extras.


Resposta longa:

Promessas:

  • Uso único "Retornar dados uma vez"
  • Sem cancelamento
  • Um ouvinte
  • Nenhum ouvinte suporta um ouvinte

Observável:

  • Retornar dados muitas vezes conforme os dados mudam
  • Suporte cancelado
  • Soquete de suporte
  • Apoie muitos Ouvintes e notifique-os quando os dados forem alterados
  • Mapa de suporte, filtro, redução
Amr Ibrahim
fonte
Eu não acho que você possa dizer que os Observáveis ​​são objetivamente melhores. Existem várias desvantagens para o Observables observadas nas várias respostas aqui. Os que mais me destacam são a complexidade do Observable e que eles não trabalham diretamente com wait / async. Pessoalmente, acho muito difícil trabalhar com eles, porque você não pode determinar o comportamento de um Observável ao usá-lo - você precisa observar o código que o gerou. Considerando que, com uma promessa, você sabe exatamente como eles funcionam, sempre. Por exemplo, às vezes a inscrição em um Observable tem efeitos colaterais (por exemplo, uma solicitação http), mas às vezes não.
Yona Appletree
Para angular, isso depende do seu caso. na maioria dos casos, trabalharemos com serviços e alguns dados que afetarão diferentes locais, soquetes, cancelamentos, mapas, filtros e reduções. então será melhor nesses casos, pois promete não apoiá-los. Então, novamente, depende do seu caso.
Amr Ibrahim
2

Embora a resposta aceita seja boa em geral, não acho que enfatize que, ao lidar com componentes angulares, você quase sempre deseja usar um observável, porque ele suporta cancelamento. As promessas não podem ser canceladas e serão resolvidas mesmo que seu componente seja destruído. Angular tende a perdoar até que não seja.

Por exemplo, qualquer detecção manual de alterações em um componente destruído causará uma exceção:

ngOnInit() {
  // promise api
  this.service.getData().then(d => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });

  // observable api
  this.service.getData().pipe(takeUntil(this.unsubscribe)).subscribe((d) => {
     this.data = d;
     this.changeDetectorRef.detectChanges();
  });
}

Se o seu componente for destruído antes da promessa ser resolvida, você receberá um attempt to use destroyed viewerro quando a promessa for resolvida.

Como alternativa, se você usar observáveis ​​com o padrão takeUntil , assim que seu componente for destruído, a assinatura será cancelada.

Este é um exemplo um pouco artificial, mas a execução de código para um componente destruído provavelmente levará a erros. A menos que você queira fazer isso por algum motivo: p

shusson
fonte
2

Algo que encontrei que não era aparente desde a primeira leitura do tutorial e da documentação foi a ideia do multicasting.

Certifique-se de que, por padrão, várias assinaturas acionarão várias execuções em um Observável. Várias assinaturas para uma única chamada HTTP Observable acionarão várias chamadas HTTP idênticas, a menos que você .share()(ative o multicast).

Uma promessa obriga você a lidar com uma coisa de cada vez, desembrulhar seus dados, lidar com exceções, ter suporte a idiomas para coisas legais como assíncrono / aguardar e, por outro lado, é bastante barebones.

Um Observable tem muitos sinos e assobios, mas você precisa entender o poder com o qual está trabalhando ou pode ser mal utilizado.

rpgFANATIC
fonte
2

Promessa:

Um manipulador de eventos assíncrono - O objeto Promise representa a conclusão (ou falha) final de uma operação assíncrona e seu valor resultante.

Sintaxe: nova promessa (executor);

Por exemplo:

var promise_eg = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve('foo');
  }, 300);
});

promise_eg.then(function(value) {
  console.log(value);
  // expected output: "foo"
});

console.log(promise_eg);

insira a descrição da imagem aqui

Sobre a Promise: Possui um pipeline, portanto, ele retornará valores apenas uma vez quando for chamado. seu manipulador unidirecional chamado uma vez, talvez você não consiga cancelar. sintaxe útil que você pode brincar, quando () e depois ()

Observáveis:

Observáveis ​​são coleções preguiçosas de vários valores ao longo do tempo. é realmente uma ótima abordagem para operações assíncronas. isso pode ser feito com o rxjs, que possui suporte para várias plataformas, pode usar com angular / react etc.

seu ato como forro de fluxo. pode ser multi pipeline. portanto, uma vez definido, você pode se inscrever para obter resultados de retorno em muitos lugares.

Sintaxe: import * as Rx from "@reactivex/rxjs"; para init:

Rx.Observable.fromEvent(button, "click"),
Rx.Subject()

etc

subscrever: RxLogger.getInstance();

Por exemplo:

import { range } from 'rxjs';
import { map, filter } from 'rxjs/operators';

range(1, 200).pipe(
  filter(x => x % 2 === 1),
  map(x => x + x)
).subscribe(x => console.log(x));

como ele suporta vários pipeline, você pode assinar o resultado em um local diferente, insira a descrição da imagem aqui tem muitas possibilidades além das promessas.

Uso: tem mais possibilidades comomap, filter, pipe, map, concatMap etc

Mohideen bin Mohammed
fonte
2

A diferença básica entre observável e promessas são:

insira a descrição da imagem aqui

Chirag
fonte
2
Por favor editar o seu post e mostrar o conteúdo real como texto em vez de imagens. Outros não podem copiar e colar de suas imagens. Veja aqui para detalhes. Obrigado.
Pang
1

Observáveis ​​são frequentemente comparados com promessas. Aqui estão algumas diferenças importantes:

Observáveis ​​são declarativos; o cálculo não inicia até a assinatura. As promessas são executadas imediatamente na criação. Isso torna os observáveis ​​úteis para definir receitas que podem ser executadas sempre que você precisar do resultado.

Observáveis ​​fornecem muitos valores. Promessas fornecem um. Isso torna os observáveis ​​úteis para obter vários valores ao longo do tempo.

Observáveis ​​diferenciam entre encadeamento e assinatura. Promessas possuem apenas cláusulas .then (). Isso torna os observáveis ​​úteis para criar receitas de transformação complexas a serem usadas por outras partes do sistema, sem causar a execução do trabalho.

Observables subscribe () é responsável por manipular erros. As promessas enviam erros às promessas da criança. Isso torna os observáveis ​​úteis para o tratamento centralizado e previsível de erros.

Essa é a diferença mais simples que você pode encontrar nos documentos do ANGULAR.IO. resposta de descanso é dada pela maioria está correta em seu próprio lugar

ankita kumari
fonte
1
  1. As promessas são focadas apenas em valores únicos ou resoluções; os observáveis ​​são o fluxo de dados.

  2. Observáveis ​​podem ser cancelados, mas promessas não podem ser canceladas.

O menos conhecido, pelo menos para mim é

  1. As promessas são sempre de natureza assíncrona, mas os observáveis ​​podem ser síncronos e assíncronos.
Vignesh
fonte
0
  1. uma promessa está ansiosa, enquanto um observável é preguiçoso,
  2. uma promessa é sempre assíncrona, enquanto um observável pode ser síncrono ou assíncrono,
  3. uma promessa pode fornecer um valor único, enquanto um observável é um
    fluxo de valores (de 0 a vários valores),
  4. você pode aplicar operadores RxJS a um Observable para obter um novo fluxo personalizado.
yogesh waghmare
fonte
-1

Observables e Promises estão nos ajudando a trabalhar com as funcionalidades assíncronas em JavaScript / typescript. Eles são muito semelhantes em muitos casos, no entanto, ainda existem algumas diferenças entre eles.

insira a descrição da imagem aqui

FAISAL
fonte
1
Por favor edite seu post e mostrar o texto real em vez de screenshots. Outros não podem copiar e colar de suas imagens. Veja aqui para detalhes. Obrigado.
Pang
Só que não o código, mas informações simples, então eu acho que não há problema em publicá-la como uma imagem
Alator
1
pare de copiar e colar dos vídeos do youtube de Kudvenkat. Voto negativo de mim! :)
Pratik
-2

Já existem muitas respostas sobre esse tópico, portanto não adiciono uma redundante.

Mas para alguém que acabou de começar a aprender Observable / Angular e se pergunta qual deles usar em comparação com o Promise , eu recomendaria que você mantivesse tudo Observable e convertesse todas as Promessas existentes em seu projeto em Observable.

Simplesmente porque a própria estrutura Angular e sua comunidade estão usando o Observable. Portanto, seria benéfico quando você integrar serviços de estrutura ou módulos de terceiros e encadear tudo.


Embora eu aprecie todos os votos negativos, mas ainda insisto na minha opinião acima, a menos que alguém faça um comentário adequado para listar alguns cenários que ainda podem ser úteis no seu projeto Angular para usar Promessas por Observáveis.

É claro que nenhuma opinião é 100% correta em todos os casos, mas pelo menos acho que 98% do tempo para projetos comerciais regulares implementados na estrutura Angular, o Observable é o caminho certo a seguir.

Mesmo que você não goste no ponto de partida do seu projeto de hobby simples, em breve perceberá quase todos os componentes com os quais interage no Angular, e a maior parte da estrutura de terceiros amigável do Angular está usando o Observables, e então acabou convertendo constantemente sua promessa para observável para se comunicar com eles.

Esses componentes incluem, entre outros: HttpClient, Construtor de formulários, Módulos / caixas de diálogo de material angular, Armazenamento / efeitos do Ngrx e ngx-bootstrap.

De fato, a única promessa do ecossistema angular com que lidei nos últimos 2 anos é APP_INITIALIZER.

Xinan
fonte