在我的Angular 7应用程序中,我有下一个函数:
getUserData(uid) {
return this.fireStore.collection('users').doc(uid).valueChanges().subscribe(data => {
this.writeCookie(data)
this.currentUser = data;
})
}
我想在另一个方法中使用这个函数:
someMethod() {
...
new Promise(this.getUserData(uid))
.then(() => {...})
...
}
但是我不能这样做,因为TypeScript抛出了一个错误:
类型为"Subscription"的参数不能赋值给类型为"Subscription"的参数(解析:(值?:{}|类似承诺〈{}〉)=〉无效,拒绝:(原因?:任意)=〉void)=〉void '。类型"订阅"未提供与签名"(解析:(值?:{}|类似承诺〈{}〉)=〉无效,拒绝:(原因:任何)=〉无效):无效(2345)
如何将getUserData()
方法转换为承诺,或者使用forJoin
?
先谢了。
5条答案
按热度按时间mkh04yzy1#
subscribe
将类型从Observable
更改为Subscription
,从而导致类型错误。你可能需要把Observable转换成Promise,同时保留函数调用,你可以通过
tap
传输Observable,然后用toPromise
转换结果,如下所示:确保创建一个完成管道,就像您可以使用
first
操作符所做的那样,否则Promise将永远无法解析。您可以在消费者中省略
new Promise(...)
。jfewjypa2#
ggradnig的实现是正确的解决方案,但是我想更深入地分析一下为什么它能工作,这样如果将来有人遇到这个问题就不会感到困惑了。
当你订阅一个观察对象时,大多数时候你只需要传入一个回调函数,这个回调函数描述了当你接收到数据流时你想要如何处理它。实际上,观察对象中可以包含3个不同的回调函数,用于不同类型的事件。它们是:
1.next-当从流中接收到数据时调用。所以如果你请求获取一些口袋妖怪的统计数据,它会调用“next”回调函数,并将数据作为输入传递。大多数时候,这是你唯一关心的数据,rxjs的创建者知道这一点,所以如果你只在订阅中包含一个回调函数,预订将默认为将“下一个”数据传递到该回调中。
1.error-非常简单明了。如果一个错误在你的可观察对象中被抛出并且没有被捕获,它将调用这个回调函数。
1.complete-当可观察对象完成时调用。
如果你想处理从一个可观察对象发出的所有不同类型的数据,你可以在订阅中编写一个观察者,如下所示:
在大多数情况下,这也是不必要的,但是当我们调用."toPromise“时,理解这些类型的事件是至关重要的()”的方法。当我们把一个可观察的转化为一个承诺时,所发生的事情是,一旦调用了Observable上的“Complete”方法,Promise将使用Observable发出的最后一个“next”数据进行解析。这意味着,如果“Complete”回调函数未被“如果你不打电话来,诺言就会无限期地挂起。
我知道你在想什么我一直在把我的http请求从Observables转换成Promises,我从来没有遇到过Promises无限期挂起的情况。这是因为只要从http调用中接收到所有数据,Angular http库就会调用Observable上的“Complete”回调函数。这是有意义的,因为一旦你从请求中接收到所有数据,你就完成了。你不期望将来有更多的数据。
这与问题中描述的情况不同,你正在调用firestore,我从经验中知道firestore使用套接字来传输信息,而不是http请求。这意味着通过连接你可能会接收到一组初始数据......然后更多的数据......然后更多的数据。它本质上是一个没有明确终点的流。所以它永远没有理由调用“完成”回调。同样的事情也会发生在行为和重播主题上。
为了避免这个问题,你需要强制Observable调用“Complete”回调函数,方法是通过管道输入“first()”或“take(1)”,这两种方法都是一样的,调用“next”回调函数,将初始数据集作为输入,然后调用“Complete”回调函数。
希望这是有用的人在那里,因为这个问题困惑了我很长一段时间。
此外,如果你仍然感到困惑,这个视频是一个很好的参考:https://www.youtube.com/watch?v=Tux1nhBPl_w
ebdffaop3#
如果您必须在getUserData方法中具有**.subscription**,则这是另一种方法。
那么你可以这样使用
0yg35tkg4#
当前您正在返回整个订阅。若要修复此问题,您需要使用toPromise
由于您正在返回上述fn中的承诺,因此无需创建新的承诺
tzcvj98z5#
您应该使用新的语法将可观察性转换为承诺: