简体   繁体   中英

Angular - combining Observables with promise

Currently, I am calling the database to extract all the conversations of a specific user. After that, I am looping through those conversations and I extract metadata such as message text, message sender and etc from each conversation. I create an object for each with its' metadata which then are all stored in an Array - in my case 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);

However, on the line where return this.createConversationObject('username', ...) is called, I have been struggling to assign a user's actual username, fetched from the database.

Basically, I am using the userKey local variable, which is obtained from the switch-case code above, in order to attempt to do the following:

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

And then pass the tempUsername in the return statement. However, I have been struggling with making the result would to be awaited - in order for the username to be fetched, before the return is called.

Does anyone have any suggestions how can I properly achieve the desired result?

Edit (after understanding the issue more closely)

Here's the code example for the proposed solution: Code example

Here are the modification that needs to be done to your code:

  • In the map(conversations => block, return the modified object with userkey appended and not the results of this.createConversationObject()

  • introduce switchMap after this and convert the Promise to Observable using rxjs -> from operator, also convert the results of the updated object returned from the previous map operation into a new Observable using rxjs -> of operators

  • now return the result of CombineLatest(OriginalObservable, fromPromiseObservable)

  • lastly you further need to map the results of these two Observable returns into one of use it directly in your call to this.createConversationObject()

  • and finally you can subscribe to the result to get the actual result as a final step

Hope this clarifies!

Original response

Here's my suggestion:

  • You could convert this.af.getUserName(userKey) promise to an observable first by using fromPromise provided by rxjs.
  • and then use this converted observable for username in your existing CombineLatest in the SwitchMap block
  • and finally use the result which would now be conversions and username in your map block to fetch the username for your return statement

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM