我在AngularJS中使用诺言有很多经验,现在正努力使我在Angular中使用Observable。
我对单个异步结果的承诺 like -它们似乎非常适合此用例-但Angular似乎热衷于将Observables用于所有内容,因此我现在尝试尽力理解使用此模式的实践。下面是一个示例,说明如何使用诺言链实现某些目标。目标是:
MyClass.value
为doSomethingAsync()
时应始终设置
叫doSomethingElse()
应该能够与
doSomethingAsync()
是否想要并等待直到完成 ,然后再使用结果
export class MyClass {
private value;
public doSomethingAsync() {
return someAsyncCall()
.then(value => {
this.value = value
});
}
}
export class MyOtherClass {
public doSomethingElse() {
const myObj = new MyClass();
let myValue;
myObj
.doSomethingAsync()
.then(value => {
myValue = value
});
}
}
我试图弄清楚如何使用Observables。
我可以在.pipe()
中将tap()
与doSomethingAsync()
一起使用来捕获值,但是问题是,除非doSomethingElse()
调用{{1 }}上返回的Observable。我不想让subscribe()
依赖于呼叫者接下来的工作。
我可以调用doSomethingAsync()
中的subscribe()
来捕获值,但是随后我不再有Observable返回。所以我想我可能不得不做这样的事情:
doSomethingAsync()
但是,这似乎过于复杂,因为我现在也必须弄乱主题,并有效地跟踪两个不同的流。
有人可以建议这样做的更好方法吗?在我看来,用诺言处理起来要容易得多……?
答案 0 :(得分:0)
正如您所说,他们非常热衷于使用rxjs。对于经典的后端,您只想调用一次,解决一个承诺,就是这样,将可观察对象转换为一个承诺,并根据设计需求返回您的承诺;要实现这一目标,请在Observable上使用rxjs中的toPromise()。
保持Observable的想法是,您观察一个端点,该端点会在数据发生变化时即时返回值,并且您可以随时接收它们,一旦完成,您就退订(离开视图或类似的视图) 。例如,一些使用websocket的api或一些实时后端(例如Firebase)。但这对于经典的后端没有意义,在传统的后端中,您将其称为端点->得到结果->就这样。因为最后,每次您想得到那里的东西时,都必须打一个新电话。
然后您的示例如下所示:
export class MyClass {
private value;
public doSomethingAsync() {
return someAsyncCall().toPromise();
}
}
export class MyOtherClass {
public doSomethingElse() {
const myObj = new MyClass();
let myValue;
myObj
.doSomethingAsync()
.then(value => {
myValue = value
});
}
}
答案 1 :(得分:0)
好的,我已经弄清楚了现在该怎么做。但是,我现在得出结论(请参见下文),这并不是使用RxJS的好方法...
export class MyClass {
private value;
public doSomethingAsync() {
const observable = someAsyncCall()
.pipe(
tap(value => {
this.value = value;
}),
share()
);
observable.subscribe();
return observable;
}
}
export class MyOtherClass {
public doSomethingElse() {
const myObj = new MyClass();
let myValue;
myObj
.doSomethingAsync()
.subscribe(value => {
myValue = value
});
}
}
doSomethingAsync()
意味着总是触发异步源操作。share()
意味着呼叫者也可以订阅而无需重新触发源。 share()
在后台使用主题工厂,这也意味着调用方可以选择重试整个序列。tap()
中的subscribe()
(而不是doSomethingAsync()
)来捕获值,这意味着如果调用方重试,它将被重新捕获-这使所有状态保持一致。 / li>
doSomethingAsync()
,它仍然会执行操作。MyClass
负责维护自己的状态-MyClass
的状态不受调用方是否执行.subscribe()
功能的影响。 / li>
MyClass
的状态仍会受到影响-这是为了保持状态的一致性而设计的,但这确实意味着我还没有完全 保留了封装。我现在得出的结论是,做到这一点的“正确”方法-不违背我认为Observables应该起作用的方式-实际上是依靠调用者来执行订阅,即:
export class MyClass {
private value;
public doSomethingAsync() {
return someAsyncCall()
.pipe(
tap(value => {
this.value = value;
})
);
}
}
export class MyOtherClass {
public doSomethingElse() {
const myObj = new MyClass();
let myValue;
myObj
.doSomethingAsync()
.subscribe(value => {
myValue = value
});
}
}
doSomethingAsync()
方法返回一个Observable,我认为通常的期望是在您对结果调用.subscribe()
之前什么都不会发生。MyClass
的“朋友”,因此可以(通过.subscribe()
方法修改其状态)。pipe()
,tap()
和subscribe()
promise.then()
将单个异步调用链接在一起,在我看来这是一个简单得多的概念。subscribe()
才能使事情发生。