แปลงสัญญาเป็น Observable


214

ฉันพยายามห่อหัวของฉันไว้กับสิ่งที่สังเกตได้ ฉันชอบวิธีที่สังเกตได้แก้ปัญหาการพัฒนาและการอ่านได้ ขณะที่ฉันอ่านมีประโยชน์มากมาย

สิ่งที่สังเกตได้บน HTTP และการรวบรวมดูเหมือนจะตรงไปตรงมา ฉันจะแปลงบางอย่างเช่นนี้เป็นรูปแบบที่สังเกตได้ได้อย่างไร

นี่คือจากองค์ประกอบบริการของฉันเพื่อให้การตรวจสอบ ฉันต้องการให้ทำงานเหมือนบริการ HTTP อื่น ๆ ใน Angular2 - พร้อมรองรับข้อมูลข้อผิดพลาดและเครื่องมือจัดการความสมบูรณ์

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

ความช่วยเหลือใด ๆ ที่นี่จะได้รับการชื่นชมมาก ทางเลือกเดียวที่ฉันมีคือสร้างEventEmitters แต่ฉันคิดว่ามันเป็นวิธีที่แย่มากที่จะทำสิ่งต่าง ๆ ในส่วนบริการ

คำตอบ:


319

หากคุณใช้ RxJS 6.0.0:

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

9
ใช้ 6.3.3, fromวิธีคืนค่าที่สังเกตได้ แต่กำลังส่งสัญญาเป็นค่าต่อการสมัครสมาชิก :(
Laxmikant Dange

1
คำตอบนี้คือ corrext สำหรับ RXJS 6+ ฉันพยายามนำเข้าจากoperatorsผ่าน "ปรีชา" - ฉันผิด
VSO

119

ลองนี้:

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

คุณสามารถหาอ้างอิงที่สมบูรณ์ไปยังผู้ประกอบ fromPromise ที่นี่


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

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

41

1 การดำเนินการ / การแปลงโดยตรง

ใช้fromเพื่อแปลงสัญญาที่สร้างขึ้นก่อนหน้านี้โดยตรงเป็นที่สังเกตได้

import { from } from 'rxjs';

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

observable$จะเป็นสิ่งที่สังเกตได้อย่างร้อนแรงซึ่งจะชดเชยมูลค่าของสัญญาให้กับสมาชิกได้อย่างมีประสิทธิภาพ

ร่างกายของสัญญาถูกดำเนินการหรือได้รับการแก้ไขแล้วเมื่อสร้างสิ่งที่สังเกตได้ หากสัญญาภายในได้รับการแก้ไขผู้สมัครสมาชิกรายใหม่ที่สามารถสังเกตได้จะได้รับมูลค่าทันที

2 การดำเนินการรอการตัดบัญชีในการสมัครสมาชิกทุกครั้ง

ใช้deferกับฟังก์ชั่นสัญญาโรงงานเป็นอินพุตเพื่อเลื่อนการสร้างและการแปลงสัญญาเป็นแบบสังเกตได้

import { defer } from 'rxjs';

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

observable$จะเป็นที่สังเกตได้เย็น

ข้อแตกต่างfromคือdeferรอสมาชิกและจากนั้นสร้างสัญญาใหม่โดยการเรียกฟังก์ชั่นโรงงานสัญญาที่กำหนด สิ่งนี้มีประโยชน์เมื่อคุณต้องการสร้างสิ่งที่สังเกตได้ แต่ไม่ต้องการให้มีการดำเนินการตามสัญญาภายใน สัญญาภายในจะถูกดำเนินการเมื่อมีคนสมัครรับข้อมูลที่สังเกตได้ ผู้สมัครสมาชิกแต่ละคนจะได้รับการติดตามใหม่ของตัวเอง

3 ผู้ประกอบการจำนวนมากยอมรับคำสัญญาโดยตรง

ส่วนใหญ่ผู้ประกอบ RxJS ที่รวม (เช่นmerge, concat, forkJoin, combineLatest... ) หรือเปลี่ยน observables (เช่นswitchMap, mergeMap, concatMap, catchError... ) ยอมรับสัญญาโดยตรง หากคุณใช้หนึ่งในนั้นคุณไม่จำเป็นต้องใช้fromคำสัญญาก่อน (แต่เพื่อสร้างความเย็นที่สังเกตได้คุณยังอาจต้องใช้defer)

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

ตรวจสอบเอกสารหรือการใช้งานเพื่อดูว่าผู้ให้บริการที่คุณใช้ยอมรับObservableInputหรือ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>;

ความแตกต่างระหว่างfromและdeferในตัวอย่าง: 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
ฉันคิดว่าความแตกต่างคือเงินทุนขอบคุณที่ชี้ให้เห็น
สตาร์สครีม

1

คุณยังสามารถใช้หัวเรื่องและเรียกใช้ฟังก์ชันถัดไป ()จากสัญญา ดูตัวอย่างด้านล่าง:

เพิ่มรหัสด้านล่าง (ฉันใช้บริการ)

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

  }
}

สร้างผู้ใช้จากองค์ประกอบเช่นด้านล่าง

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


กลุ่มตัวอย่างเป็นเครื่องจักรระดับต่ำ rxjsอย่าใช้วิชายกเว้นกรณีที่คุณกำลังขยาย
polkovnikov.ph

ฉันแค่ให้ทางออก
Shivang Gupta

อย่างน้อยคุณก็สามารถแสดงnew Observable(observer => { ... observer.next() ... })วิธีการใช้งานได้ แม้ว่ามันจะเป็นการใช้งานซ้ำของฟังก์ชั่นที่รู้จักกันดีก็จะตอบคำถามโดยตรงและจะไม่เป็นอันตรายต่อผู้อ่าน
polkovnikov.ph

1

นอกจากนี้คุณยังอาจจะใช้Defer ข้อแตกต่างที่สำคัญคือสัญญาจะไม่แก้ไขหรือปฏิเสธอย่างกระตือรือร้น


0

คุณสามารถเพิ่มเสื้อคลุมรอบฟังก์ชั่นสัญญาเพื่อส่งคืนผู้สังเกตการณ์ได้

  • การสร้างLazy Observable โดยใช้ตัวดำเนินการdefer ()ซึ่งอนุญาตให้คุณสร้าง Observable เฉพาะเมื่อ Observer สมัครสมาชิกเท่านั้น
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);
   }
)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.