loading...

Sorting arrays in Javascript by date

kodaman2 profile image Fernando B 🚀 ・1 min read

I am working on a small project which gives you a list of branches on a git repo, and generates link markdown. The goal is for when someone creates a tutorial they can make branches for the progressive steps, and then easily generate the contents list when done, and paste on a readme. I know is silly. I can easily do it in the terminal with git, and maybe with a small python program or bash script to print markdown.

I've barely done any web dev, so excuse my 1995 webpage, be gentle with my js is probably ugly. I've never done any javascript before, nor asynch stuff. Anyways I wrote a small js file locally and ran with node, and I am able to sort my array of objects by date, however same function is not working with my generatrix site even though the sort function is getting called.

Overall generatrix pulls refs of whatever repo using the github api with a callback func, then checks each branch date with another callback func. Last thing to do is to sort by date, and output to the text area as a link markdown format. Any help would be appreciated.

Repo is here

Webpage here I've added a bunch of console logs too.

alt text

As you can see on the console, sorting doesn't work. : (
Setup-01 is older than Setup-02

alt text

Posted on by:

kodaman2 profile

Fernando B 🚀

@kodaman2

Coding space junkie with a sprinkle of writer heart. DMs open for any questions or comments. 🙂

Discussion

markdown guide
 

I think the sorting is working, is just that the fetching of the date is asynchronous, which means that sometimes you get the dates BEFORE the sort is called, sometimes you get it after (If you click a few times you'll notice that the objects in array sometimes have the date, sometimes they don't).

Inside getBranchNames you call getCommitDate and inside it you call a HTTP GET to retrieve the date, but the JS doesn't guarantee that the callback is going to finish before the loop is done, which means you might call sort on an unfinished array.

It's not a super easy solution, because you're essentially sending an async call for each commit and hoping the GET finishes before the sort function is called.

Some possible solutions:

  1. you make those Ajax calls synchronous, but you're going to block the UI until they all return
  2. you switch to jQuery and wait for multiple requests to finish, an example here: stackoverflow.com/a/6558326/4186181
  3. you use ES6 and things like Promise.all + the fetch API or a third party library but I think it'd be too much to learn in one go just for this example
 

Thanks for the awesome tips. I was looking into the promises. So essentially I need to perform getBranches, getCommitDate, and then sort specifically in that order. I was sort of thinking it was something wrong with my async calls since well I had zero experience before today.

Edit: Nvm not in that order, I need to loop to all branches first to get all the dates then sort.

 

Quick tip on the note of async stuff: If you can afford to not run on Internet Explorer and Opera Mini, use Promises. They solve most of the issues inherent in the older async functionality present in JavaScript, and also tend to be more efficient.

I think I can live without IE lol.

 

One comment in general, you might want to consider using JavaScript's native Date type. This won't necessarily make the sorting any easier, but it may make other aspects of date handling (such as formatting them for display to the user) significantly simpler.

As far as the actual sorting, the reason it's not working is that you're trying to subtract strings for the comparison, which obviously won't work. Simply converting the code to use the native Date type as mentioned above would actually let everything work as-is right now, but there are a couple of other approaches that come to mind:

  • Instead of storing the BranchModel instances in an array, store them as properties of a plain object (IOW, a mapping or dictionary in other language terms) with the keys being the date strings. You can then do something like this:
// items is the mapping you want sorted values from based on keys

let tmp = Object.keys(items) // Get a list of the keys.
tmp.sort() // Sort it.
tmp.map((i) => items[i]) // Replace each key in the list 
                         // with the corresponding value from items.
                         // After this, tmp is now an array of the values
                         // in sort order, and can be used directly.
  • If you're willing to add a dependency, you can actually do this easily with Lodash using the _.sortBy() function. Code for that would look like this:
// items is the array to sort.
// This uses a shorthand form not mentioned in the Lodash documentation
// to sort by a specific named property of each element.

items = _.sortBy(items, ['_date'])

Also, one general JavaScript tip: Anything that doesn't actually depend on the DOM being safe to manipulate shouldn't be inside a window.onload handler. Put simply, there's no reason to wait to define functions or values or perform computations that don't need the page to be fully loaded until the page is fully loaded. Running those without waiting can actually help speed up load times, and anything outside of a window.onload handler is essentially certain to execute before the contents of any of the handlers because of how JavaScript actually handles events internally.

 

Thanks for the awesome tips. window.onload is just a noob mistake, I'll try to read documentation on that. I think I added it in the beginning as something wasn't working, found it somewhere on SO.

Good tip on adding Lodash. I'll revisit this tomorrow, my brain is literally fried lol. Is what happens when trying to make a new project while learning a new language lol.

 

window.onload is just a noob mistake, I'll try to read documentation on that. I think I added it in the beginning as something wasn't working, found it somewhere on SO.

It's not necessarily a mistake to use window.onload (unless of course you're using a library that provides the same functionality). You should always make sure the DOM is safe to manipulate before you try to do so, and window.onload is one of the ways to do that.

Good tip on adding Lodash.

Lodash one of the few things that I'm pretty much always willing to add to a project, it's not exactly small, but it's just so darn useful.

Is what happens when trying to make a new project while learning a new language lol.

By the way, if you haven't already seen it, Mozilla has a rather good web developer reference site that's remarkably helpful when you're just starting out learning JavaScript.