我试图围绕着可观察者。我喜欢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
。但我想这是在服务部分做事的可怕方式
答案 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。
在示例中,from
和defer
之间的区别: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返回给观察者。
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$);
}
我希望它对更新版本的更新代码有所帮助:')