-1

I have a Firebase service provider function returning a set of data by a promise object:

getPreviousChats(groupKey: string, offset: string): Promise<any> {
  return new Promise((resolve, reject) => {
    // let previousChats: Array<any> = [];
    let previousChats: any[] = [];
    const chatRef = this.chatsRef.child(groupKey).orderByKey().endAt(offset).limitToLast(5);
    chatRef.once('value', snapshot => {
      snapshot.forEach(childSnapshot => {
        previousChats.push({
          id: childSnapshot.key,
          message: childSnapshot.val().message,
          createTime: childSnapshot.val().createTime
        });
        return false; // forEach returns boolean
      });
    });
    resolve(previousChats);
  });
}

Meanwhile, an Ionic page function calls getPreviousChats() to retrieve previous chat data and add it to current page layout by unshift():

loadPreviousChats(refresher) {
  this.dataService.getPreviousChats(this.groupKey, this.chats[0].id).then(data => {
    this.chats.unshift(data);
  }, (error) => {
    console.log('loadPreviousChats error: ', JSON.stringify(error));
  });
  setTimeout(() => {
    console.log('Async operation has ended');
    refresher.complete();
  }, 1000); 
}

Unfortunately, somehow this.chats.unshift(data); inserts the data in front of current this.chats array with an extra layer of array:

this.chats:  Array[6]
              0: Array[5]
                0: Object
                1: Object
                2: Object
                3: Object
                4: Object
                 length: 5
                 __proto__: Array[0]
              1: Object
              2: Object
              3: Object
              4: Object
              5: Object
               length: 6
               __proto__: Array[0]

So, what am I missing here?

israkir
  • 2,111
  • 7
  • 30
  • 39

2 Answers2

1

So, what am I missing here?

That that's what unshift does: It takes the value you give it and inserts it at the beginning of the array. The value you're giving it is an array reference, so that's what it puts in the array.

If you want to append those entries to this.chats, you can do that with push; it's a bit awkward in ES5 and earlier:

this.chats.push.apply(this.chats, data);

a bit clearer in ES2015+ with spread syntax:

this.chats.push(...data);

Side note: You're also falling prey to this problem: You're resolving your promise in getPreviousChats too soon, before the once callback is called (I'm assuming it's an asynchronous operation, otherwise it seems odd for it to use a callback like that). Move the resolve call into the callback.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Cool! The problem was really about "resolve". After moving it to callback, everything works fine. Thanks! – israkir Jan 30 '17 at 09:16
1

I guess you can insert the new Array Items into the existing one like so:

let chats = [...newChats, ...oldChats]; //or oldChats first

or, you can use concat like so:

let chats = oldChats.concat(newChats);

I would prefer method one, since it creates a swallow copy of each array, without modifying the originals.

philipp
  • 15,947
  • 15
  • 61
  • 106