makat
makat

Reputation: 164

How to display only the latest data received?

Hey I am trying to show only the latest message of the day,

Thing is I am not sure how to do that as my code only picks up the one I first wrote..

it's not even the first object in the array.. but it still takes it.

*Note that this code runs every few seconds in intervals to check for new data received.

Below is the response I am using my logic on and the code with the logic

enter image description here

isMOTD = false;
    var i = 0;
    var MOTD = "";
    while (messages[i].text && isMOTD == false) {
        i++;

     isMOTD = messages[i].text.includes("MOTD");

     if (isMOTD) 
       MOTD = messages[i].text;

    }

               if (isMOTD) {
        console.log(MOTD+' ' +'THIS IS MSG OF THE DAY')
                  $('.content', el).html(MOTD);
               }

      }
    };

Upvotes: 0

Views: 692

Answers (2)

Nicholas Tower
Nicholas Tower

Reputation: 85132

I would do something like this:

var MOTD = messages.filter(message => message.text.includes("MOTD"))
    .reduce((a, b) => a.ts > b.ts ? a : b, {ts: -1, text: ''})
    .text;

$('.content', el).html(MOTD);

The .filter() creates a new array which only includes messages with MOTD in them.

the .reduce() is going through that filtered array and keeping only the message who's timestamp is highest. I also have it default to an empty string if there are no strings that contain MOTD

And then .text, to deal with just the string, not the timestamps.


EDIT: i've been requested to add some more explanation.

First: arrow functions. EcmaScript 2015 (one of the newer versions of javascript) gave a new way to write functions. When you see an =>, think "function". Rather than doing this:

function (a, b) {
    return a + b;
}

you can do this:

(a, b) => {
    return a + b;
}

Or if there's just one statement as in this case, you can leave off the curly brackets, the semicolon, and the return:

(a, b) => a + b

Second: .filter. All arrays have a function on them called .filter. As the name suggests, the purpose is to filter the array. You pass in a function that describes how you want it to be filtered, and then it creates a new array with just the matching elements.

So consider the following:

var myArray = [1, 2, 3, 15, 18, 200];
var evenNumbers = myArray.filter(function (num) {
    return num % 2 == 0
});

It will loop through the array, and for each element of the array, it calls the function i specified. If the function returns true, then that element is included. If the function returns false, then the element is not included. So for this sample code, evenNumbers will equal [2, 18, 200]

For your case, the filter that i'm doing is:

messages.filter(function (message) {
   return message.text.includes("MOTD");  
});

So the array that's returned by this will contain all messages who's text includes "MOTD". messages that lack "MOTD" are excluded.


Third: .reduce. All arrays have this function as well. Reduce is quite a versatile function, but the general purpose is to take your array, and in some way boil it down (or "reduce" it) to a single value. You pass in some function that you want to be called for every element of the array. When your function returns a value, that value gets carried forward and used the next time the function is run. Here's an example where i want to sum up all the numbers in an array:

var myArray = [1, 2, 3, 4];
var total = myArray.reduce(function (sumSoFar, current) {
    var newSum = sumSoFar + current;
    return newSum;
}, 0); //<--- this 0 is the initial value

So here's how it works: It's going to start with the initial value of 0, and then it calls the function. SumSoFar will be 0 at this point (because of the intial value), and current is 1 (because we're starting with the first element of the array, which has a value of 1). The function adds them together, and then returns a new sum of 1. Then the function gets called again, but now sumSoFar is 1 (because that's what was returned the last time), and current is 2 (because we're looking at the second element). It adds 1 + 2, and returns a new sum of 3. And so it continues, adding 3 + 3 to get 6, then adding 6 + 4 to get 10. We're done going the the array, so the final value is 10.

In your case, i want to step through the array and find only the message with the most recent timestamp. I start with an initial value of {ts: -1, text: ''}, because in case there are no messages with "MOTD" in them, i want to have the empty string be the result.

.reduce(function (mostRecentMessageSoFar, currentMessage) {
   if (mostRecentMessageSoFar.ts > currentMessage.ts) {
      return mostRecentMessageSoFar;
   } else {
      return currentMessage;
   }
}, {ts: -1, text: ''});

So this will walk its way through the array (and remember, we're walking through the filtered array, so they all have "MOTD" in them), it is looking for the most recent message. Any time currentMessage is more recent than the best we've found so far, it switches to that one being the best so far. And in the end, we get the most recent message from the entire array.

That final message is an object that looks something like this:

{
   type: 'message',
   user: 'U0GL3BR52',
   text: 'SOLVE MORE CASES #MOTD',
   ts: 1505236695.000533
}

Only the text needs to be put into the dom, so i access that with .text


So, in long form, my solution is this:

var MOTDMessages = messages.filter(function (message) {
   return message.text.includes("MOTD");
});

var MostRecentMOTDMessage = MOTDMessages.reduce(
   function (mostRecentMessageSoFar, currentMessage) {
      if (mostRecentMessageSoFar.ts > currentMessage.ts) {
         return mostRecentMessageSoFar;
      } else {
         return currentMessage;
      }
   }, {ts: -1, text: ''});

var MOTDText = MostRecentMOTDMessage.text;

$('.content', el).html(MOTDText);

Upvotes: 4

Jonas Wilms
Jonas Wilms

Reputation: 138457

Just sort your message after time descending:

 messages.sort((a,b) => b.ts - a.ts );

Then just take the first one:

messages[0]

Upvotes: 0

Related Questions