Konversikan Janji menjadi Teramati

214

Saya mencoba untuk membungkus kepala saya di sekitar yang bisa diamati. Saya suka cara yang diamati diamati memecahkan masalah pengembangan dan keterbacaan. Ketika saya membaca, manfaatnya sangat besar.

Dapat diamati pada HTTP dan koleksi tampaknya lurus ke depan. Bagaimana saya bisa mengubah sesuatu seperti ini menjadi pola yang bisa diamati.

Ini dari komponen layanan saya, untuk memberikan otentikasi. Saya lebih suka ini bekerja seperti layanan HTTP lain di Angular2 - dengan dukungan untuk penangan data, kesalahan dan penyelesaian.

firebase.auth().createUserWithEmailAndPassword(email, password)
  .then(function(firebaseUser) {
    // do something to update your UI component
    // pass user object to UI component
  })
  .catch(function(error) {
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
    // ...
  });

Bantuan apa pun di sini akan sangat dihargai. Satu-satunya solusi alternatif yang saya miliki adalah menciptakan EventEmitter. Tapi saya rasa itu cara yang buruk untuk melakukan hal-hal di bagian layanan

Krishnan Sriram
sumber

Jawaban:

320

Jika Anda menggunakan RxJS 6.0.0:

import { from } from 'rxjs';
const observable = from(promise);
Guillaume
sumber
9
Menggunakan 6.3.3, frommetode pengembalian dapat diamati tetapi mengirimkan janji sebagai nilai untuk langganan. :(
Laxmikant Dange
1
Jawaban ini adalah corrext untuk RXJS 6+. Saya mencoba mengimpor dari operators"intuisi" - saya salah.
VSO
119

coba ini:

import 'rxjs/add/observable/fromPromise';
import { Observable } from "rxjs/Observable";

const subscription = Observable.fromPromise(
    firebase.auth().createUserWithEmailAndPassword(email, password)
);
subscription.subscribe(firebaseUser => /* Do anything with data received */,
                       error => /* Handle error here */);

Anda dapat menemukan referensi lengkap dari fromPromise operator di sini .

Ayah baptis
sumber
47
import 'rxjs/add/observable/fromPromise';
Simon Briggs
16
import { Observable } from "rxjs/Observable"; :)
Luckylooke
41

1 Eksekusi / Konversi Langsung

Gunakan fromuntuk secara langsung mengonversi janji yang dibuat sebelumnya menjadi yang dapat diobservasi.

import { from } from 'rxjs';

// getPromise() will only be called once
const observable$ = from(getPromise());

observable$akan menjadi sesuatu yang dapat diobservasi panas yang secara efektif memutar kembali nilai janji kepada pelanggan.

Badan yang dijanjikan sedang dieksekusi atau telah diselesaikan ketika yang diamati diamati. Jika janji batin telah dipecahkan, pelanggan baru yang dapat diamati akan segera mendapatkan nilainya.

2 Eksekusi Ditangguhkan Pada Setiap Berlangganan

Gunakan deferdengan fungsi pabrik janji sebagai input untuk menunda pembuatan dan konversi janji menjadi yang dapat diobservasi.

import { defer } from 'rxjs';

// getPromise() will be called every time someone subscribes to the observable$
const observable$ = defer(() => getPromise());

observable$akan menjadi dingin yang bisa diamati .

Perbedaannya fromadalah bahwa defermenunggu pelanggan dan hanya kemudian menciptakan janji baru dengan memanggil fungsi pabrik janji yang diberikan. Ini berguna ketika Anda ingin membuat yang dapat diamati tetapi tidak ingin janji batin dieksekusi segera. Janji batin hanya akan dieksekusi ketika seseorang berlangganan yang dapat diamati. Setiap pelanggan juga akan mendapatkan diamati baru sendiri.

3 Banyak Operator Menerima Janji Secara Langsung

Kebanyakan operator RxJS yang menggabungkan (misalnya merge, concat, forkJoin, combineLatest...) atau mengubah diamati (misalnya switchMap, mergeMap, concatMap, catchError...) menerima janji-janji secara langsung. Jika Anda menggunakan salah satunya, Anda tidak harus menggunakan fromuntuk membungkus janji terlebih dahulu (tetapi untuk membuat dingin dapat diamati Anda masih harus menggunakandefer ).

// Execute two promises simultaneously
forkJoin(getPromise(1), getPromise(2)).pipe(
  switchMap(([v1, v2]) => v1.getPromise(v2)) // map to nested Promise
)

Periksa dokumentasi atau implementasi untuk melihat apakah operator yang Anda gunakan menerima ObservableInputatau SubscribableOrPromise.

type ObservableInput<T> = SubscribableOrPromise<T> | ArrayLike<T> | Iterable<T>;
// Note the PromiseLike ----------------------------------------------------v
type SubscribableOrPromise<T> = Subscribable<T> | Subscribable<never> | PromiseLike<T> | InteropObservable<T>;

Perbedaan antara fromdan deferdalam contoh: https://stackblitz.com/edit/rxjs-6rb7vf

const getPromise = val => new Promise(resolve => {
  console.log('Promise created for', val);
  setTimeout(() => resolve(`Promise Resolved: ${val}`), 5000);
});

// the execution of getPromise('FROM') starts here, when you create the promise inside from
const fromPromise$ = from(getPromise('FROM'));
const deferPromise$ = defer(() => getPromise('DEFER'));

fromPromise$.subscribe(console.log);
// the execution of getPromise('DEFER') starts here, when you subscribe to deferPromise$
deferPromise$.subscribe(console.log);
fridoo
sumber
4
Saya pikir perbedaan itu adalah modal, terima kasih telah menunjukkannya.
Starscream
1

Anda juga dapat menggunakan Subjek dan memicu fungsi () berikutnya dari janji. Lihat contoh di bawah ini:

Tambahkan kode seperti di bawah ini (saya menggunakan layanan)

class UserService {
  private createUserSubject: Subject < any > ;

  createUserWithEmailAndPassword() {
    if (this.createUserSubject) {
      return this.createUserSubject;
    } else {
      this.createUserSubject = new Subject < any > ();
      firebase.auth().createUserWithEmailAndPassword(email,
          password)
        .then(function(firebaseUser) {
          // do something to update your UI component
          // pass user object to UI component
          this.createUserSubject.next(firebaseUser);
        })
        .catch(function(error) {
          // Handle Errors here.
          var errorCode = error.code;
          var errorMessage = error.message;
          this.createUserSubject.error(error);
          // ...
        });
    }

  }
}

Buat Pengguna Dari Komponen seperti di bawah ini

class UserComponent {
  constructor(private userService: UserService) {
    this.userService.createUserWithEmailAndPassword().subscribe(user => console.log(user), error => console.log(error);
    }
  }

Shivang Gupta
sumber
Subjek adalah mesin level rendah. Jangan gunakan subjek, kecuali untuk kasus saat Anda memperpanjang rxjs.
polkovnikov.ph
Saya hanya memberikan solusi.
Shivang Gupta
Setidaknya Anda bisa menunjukkan new Observable(observer => { ... observer.next() ... })cara untuk mengimplementasikannya. Meskipun itu akan menjadi implementasi ulang dari fungsi terkenal yang sudah ada, itu akan langsung menjawab pertanyaan dan tidak akan berbahaya bagi pembaca.
polkovnikov.ph
1

Anda juga dapat menggunakan penundaan . Perbedaan utama adalah bahwa janji itu tidak akan menyelesaikan atau menolak dengan penuh semangat.

Mateja Petrovic
sumber
0

Anda dapat menambahkan pembungkus di sekitar fungsi janji untuk mengembalikan Pengamatan kepada pengamat.

  • Membuat Lazy Observable menggunakan defer () operator yang memungkinkan Anda untuk membuat Observable hanya ketika Observer berlangganan.
import { of, Observable, defer } from 'rxjs'; 
import { map } from 'rxjs/operators';


function getTodos$(): Observable<any> {
  return defer(()=>{
    return fetch('https://jsonplaceholder.typicode.com/todos/1')
      .then(response => response.json())
      .then(json => {
        return json;
      })
  });
}

getTodos$().
 subscribe(
   (next)=>{
     console.log('Data is:', next);
   }
)

khizer
sumber