Chuyển đổi lời hứa thành quan sát


214

Tôi đang cố gắng để quấn đầu của tôi xung quanh quan sát. Tôi thích cách quan sát giải quyết các vấn đề phát triển và dễ đọc. Khi tôi đọc, lợi ích là rất lớn.

Các quan sát trên HTTP và các bộ sưu tập dường như là thẳng về phía trước. Làm thế nào tôi có thể chuyển đổi một cái gì đó như thế này để mô hình quan sát được.

Đây là từ thành phần dịch vụ của tôi, để cung cấp xác thực. Tôi thích điều này hoạt động như các dịch vụ HTTP khác trong Angular2 - với sự hỗ trợ cho các trình xử lý dữ liệu, lỗi và hoàn thành.

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;
    // ...
  });

Bất kỳ trợ giúp ở đây sẽ được nhiều đánh giá cao. Giải pháp thay thế duy nhất tôi có là tạo EventEmitters. Nhưng tôi đoán đó là một cách khủng khiếp để làm mọi thứ trong phần dịch vụ

Câu trả lời:


315

Nếu bạn đang sử dụng RxJS 6.0.0:

import { from } from 'rxjs';
const observable = from(promise);

9
Sử dụng 6.3.3, fromphương thức trả về có thể quan sát được nhưng nó đang gửi lời hứa dưới dạng giá trị cho các đăng ký. :(
Laxmikant Dange

1
Câu trả lời này là corrext cho RXJS 6+. Tôi đã cố gắng nhập từ operatorsthông qua "trực giác" - tôi đã sai.
VSO

119

thử cái này:

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 */);

bạn có thể tìm thấy tài liệu tham khảo đầy đủ cho toán tử fromPromise tại đây .


47
import 'rxjs/add/observable/fromPromise';
Simon Briggs

16
import { Observable } from "rxjs/Observable"; :)
Luckylooke

40

1 Thực hiện / Chuyển đổi trực tiếp

Sử dụng fromđể trực tiếp chuyển đổi một lời hứa được tạo trước đó thành một lời quan sát.

import { from } from 'rxjs';

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

observable$sẽ là một quan sát nóng mà có hiệu quả thay thế giá trị hứa hẹn cho các thuê bao.

Phần thân lời hứa đang được thực thi hoặc đã được giải quyết khi có thể quan sát được. Nếu lời hứa bên trong đã được giải quyết, một thuê bao mới có thể quan sát được sẽ nhận được giá trị của nó ngay lập tức.

2 thực thi bị hoãn trên mỗi lượt đăng ký

Sử dụng defervới chức năng nhà máy lời hứa làm đầu vào để trì hoãn việc tạo và chuyển đổi lời hứa thành có thể quan sát được.

import { defer } from 'rxjs';

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

observable$sẽ là một quan sát lạnh .

Sự khác biệt fromdeferchờ đợi một thuê bao và chỉ sau đó tạo ra một lời hứa mới bằng cách gọi chức năng nhà máy lời hứa đã cho. Điều này hữu ích khi bạn muốn tạo một quan sát nhưng không muốn lời hứa bên trong được thực thi ngay lập tức. Lời hứa bên trong sẽ chỉ được thực hiện khi ai đó đăng ký có thể quan sát được. Mỗi thuê bao cũng sẽ có được quan sát mới của riêng mình.

3 Nhiều nhà khai thác chấp nhận lời hứa trực tiếp

Hầu hết các nhà khai thác RxJS kết hợp (ví dụ merge, concat, forkJoin, combineLatest...) hoặc chuyển đổi quan sát (ví dụ switchMap, mergeMap, concatMap, catchError...) chấp nhận lời hứa trực tiếp. Nếu bạn vẫn đang sử dụng một trong số họ thì trước tiên bạn không phải sử dụng fromđể thực hiện lời hứa (nhưng để tạo ra một thứ lạnh có thể quan sát được, bạn vẫn có thể phải sử dụng defer).

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

Kiểm tra tài liệu hoặc triển khai để xem nhà điều hành bạn đang sử dụng chấp nhận ObservableInputhay 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>;

Sự khác biệt giữa fromdefertrong một ví dụ: 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);

4
Tôi nghĩ rằng sự khác biệt đó là vốn, cảm ơn vì đã chỉ ra nó.
Starscream

1

Bạn cũng có thể sử dụng Chủ đề và kích hoạt chức năng tiếp theo () của nó từ lời hứa. Xem mẫu dưới đây:

Thêm mã như dưới đây (Tôi đã sử dụng dịch vụ)

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);
          // ...
        });
    }

  }
}

Tạo người dùng từ thành phần như bên dưới

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


Đối tượng là máy móc cấp thấp. Không sử dụng các đối tượng, ngoại trừ các trường hợp khi bạn gia hạn rxjs.
polkovnikov.ph

Tôi chỉ đưa ra một giải pháp.
Shivang Gupta

Bạn ít nhất có thể có new Observable(observer => { ... observer.next() ... })cách hiển thị để thực hiện nó. Mặc dù nó sẽ là sự tái hiện của chức năng nổi tiếng hiện có, nó sẽ trực tiếp trả lời câu hỏi và sẽ không gây hại cho độc giả.
polkovnikov.ph

1

Bạn cũng có thể sử dụng defer . Sự khác biệt chính là lời hứa sẽ không giải quyết hoặc từ chối một cách háo hức.


0

Bạn có thể thêm một trình bao bọc xung quanh chức năng hứa hẹn để trả lại một Observable cho người quan sát.

  • Tạo một Lazy Observable bằng cách sử dụng toán tử defer () cho phép bạn tạo Observable chỉ khi Observer đăng ký.
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);
   }
)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.