【问题标题】:Angular - combining Observables with promiseAngular - 将 Observables 与 Promise 相结合
【发布时间】:2018-12-25 18:12:48
【问题描述】:

目前,我正在调用数据库以提取特定用户的所有对话。之后,我循环浏览这些对话,并从每个对话中提取元数据,例如消息文本、消息发送者等。 我为每个对象及其元数据创建一个对象,然后将其全部存储在一个数组中——在我的例子中是this.recentChats

this.af.getObservable(`userChats/${this.userID}/`).pipe(
  // we map the array of conversations to an array of the (before inner) observables

  map(recentConversations =>
    recentConversations.map(conversation =>
      this.af.getObservableSortByVar(`allChats/${conversation.conversationID}/`, 'lastUpdate'))),

  // combine the observables. will emit a new value of ALL conversation data when one of the conversations changes

  switchMap(recentConversations => combineLatest(recentConversations)),
  // map each conversation to the conversation object 
  map(conversations =>
    conversations.map(conversationData => {
      let userKey, lastMessage, lastMessageText, lastMessageSender, lastMessageDate;

      for (let i = 0; conversationData.length > i; i++) {
        switch (conversationData[i].key) {
          case 'messages': {
            lastMessage = (conversationData[i][Object.keys(conversationData[i])[Object.keys(conversationData[i]).length - 1]]);
            lastMessageText = lastMessage.message;
            lastMessageSender = lastMessage.sender;
            lastMessageDate = lastMessage.date;
          }
          case 'users': {
            userKey = conversationData[i].userKey;
          }
        }
      }
      return this.createConversationObject('username', userKey, lastMessageSender, lastMessageText, lastMessageDate);
    }))
).subscribe(recentChats => this.recentChats = recentChats);

但是,在调用return this.createConversationObject('username', ...) 的那一行,我一直在努力分配从数据库中获取的用户的实际用户名。

基本上,我使用userKey 局部变量,它是从上面的 switch-case 代码中获得的,以便尝试执行以下操作:

let tempUsername;
this.af.getUserName(userKey).then((username) => {
   tempUsername = username;
}

然后在return语句中传递tempUsername。但是,我一直在努力等待结果 - 为了在调用 return 之前获取用户名。

有没有人有任何建议我怎样才能正确地达到预期的结果?

【问题讨论】:

  • this.af.getObservableSortByVar() 是否也返回 Observable

标签: angular firebase-realtime-database promise observable angularfire2


【解决方案1】:

编辑(在更深入地了解问题后)

以下是建议解决方案的代码示例:Code example

以下是需要对您的代码进行的修改:

  • map(conversations =>块中,返回带有userkey的修改后的对象,而不是this.createConversationObject()的结果

  • 在此之后引入switchMap,并使用rxjs -> from操作符将Promise转换为Observable,同时将之前map操作返回的更新对象的结果转换为使用rxjs -> of操作符的新Observable

  • 现在返回CombineLatest(OriginalObservable, fromPromiseObservable)的结果

  • 最后,您还需要将这两个 Observable 返回的结果映射到其中之一,直接在您对this.createConversationObject()的调用中使用它

  • 最后您可以订阅结果以获得实际结果作为最后一步

希望这可以澄清!

原始回复

这是我的建议:

  • 您可以先使用 rxjs 提供的 fromPromisethis.af.getUserName(userKey) 承诺转换为可观察对象。
  • 然后在 SwitchMap 块中的现有 CombineLatest 中使用此转换后的 observable 作为用户名
  • 最后使用 map 块中的转换结果和用户名来获取返回语句的用户名

【讨论】:

  • 但是,userKey 局部变量是在 map(conversations => 块中定义的。所以基本上,我不能在它之前实际使用它。你对我该如何处理有什么建议吗?
  • 只是为了更清楚地理解它:在您的map(conversations => 块中,您使用switch -> case 获取userkey。并且有这个承诺代码可以在createConversationObject(..) 方法中从userkey 获取用户?
  • 正确!获取userKey 后,我想在promise 中使用它,以便对数据库进行新调用并检索用户名。检索名称后,我想将其传递给createConversationObject(..)
  • 酷。所以基本上你应该做的是不要在map(conversations => 块中调用createConversationObject,因为你的createConversationObject 将是链中的最后一步;你应该在最后这样做。但首先您应该使用userkey 返回映射数据。在您现有的块之后引入另一个 map 块,并将您的 promise 块添加为转换为可观察返回的块。您可能需要在您的链中添加 filter 之后才能调用 createConversationObject,仅当您有由 promise 返回的 username 时。
  • 没问题,给我一些时间,我可能会根据我们的讨论编辑我上面的答案。
猜你喜欢
  • 2013-04-13
  • 2018-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多