将承诺转换为可观察的

时间:2016-09-04 16:49:58

标签: angular firebase firebase-authentication

我试图围绕着可观察者。我喜欢observables解决开发和可读性问题的方式。在我读到的时候,好处是巨大的。

HTTP和集合上的可观察量似乎很简单。如何将这样的东西转换为可观察的模式。

这是来自我的服务组件,用于提供身份验证。我希望它能像Angular2中的其他HTTP服务一样工作 - 支持数据,错误和完成处理程序。

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

这里的任何帮助将不胜感激。我唯一的替代解决方案是创建EventEmitter。但我想这是在服务部分做事的可怕方式

8 个答案:

答案 0 :(得分:160)

如果您使用的是RxJS 6.0.0:

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

答案 1 :(得分:107)

试试这个:

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

您可以找到fromPromise operator here

的完整参考

答案 2 :(得分:6)

来自

使用from直接将先前创建的Promise转换为Observable。

import { from } from 'rxjs';

const observable = from(promise);

由于内部Promise已创建(或将与Observable同时创建),因此Promise的主体正在执行,或者在创建Observable时已被解析。如果内部Promise已解决,则可观察对象的新订阅者将立即获得其值。

推迟

defer与Promise工厂函数一起用作输入,以延迟Promise的创建和转换为Observable。

import { defer } from 'rxjs';

// getPromise has no parameters and returns a Promise
const observable = defer(getPromise)

// getPromise has parameters and returns a Promise
const observable = defer(() => getPromise(myParameters));

from的区别在于defer等待订户,然后才通过调用给定的Promise工厂函数来创建新的Promise。当您要创建一个Observable但又不想立即执行内部Promise时,这很有用。仅当某人订阅了Observable时,才会执行内部Promise。每个订阅者还将获得自己的新Observable。

在示例中,fromdefer之间的区别:https://stackblitz.com/edit/rxjs-yye14a

答案 3 :(得分:1)

您也可以使用defer。主要区别在于,诺言不是不会急切解决或拒绝。

答案 4 :(得分:0)

您还可以使用主题并从promise触发其 next()函数。参见下面的示例:

添加如下所示的代码(我使用过服务)

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

答案 5 :(得分:0)

您可以在promise功能周围添加包装器,以将Observable返回给观察者。

  • 使用 defer()运算符创建 Lazy 可观察对象,该操作符允许您仅在观察者订阅时创建观察对象。
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);
   }
)

答案 6 :(得分:0)

import { from } from 'rxjs';

from(firebase.auth().createUserWithEmailAndPassword(email, password))
.subscribe((user: any) => {
      console.log('test');
});

这是一个较短的版本,结合了上述一些答案,可以将您的代码从承诺转换为可观察的。

答案 7 :(得分:0)

这是 Rxjs 提供的 toPromise() 运算符, 就像代码示例演示的那样:

@Injectable({
  providedIn: 'root'
})
export class InventoryService {
  constructor(private httpClient: HttpClient) {}

  getCategories(): Observable<Category[]> {
    const url = 'https://www.themealdb.com/api/json/v1/1/categories.php';

    return this.httpClient.get<CategoriesResponse>(url).pipe(
      map(response => response.categories)
    );
  }
}

在您的组件中,您可以应用 toPromise() 运算符:

export class AppComponent {
  categories: any[];

  constructor(private inventoryService: InventoryService) {}

  public async loadCategories() {
    this.categories = await this.inventoryService
      .getCategories()
      .**toPromise()**

但目前不推荐使用 Rxjs7+,建议使用 lastValueFrom() 运算符:

  public async loadCategories() {
    const categories$ = this.inventoryService.getCategories();
    this.categories = await **lastValueFrom**(categories$);
  }

我希望它对更新版本的更新代码有所帮助:')

相关问题