Thoughts

Tag: javascript

Promises – What are they and how do I use them?

While Javascript is single threaded, we as humans are not. We have the ability to process multiple requests at the same time. This enables us to efficiently go about our days without letting minor obstacles stop our progress. If we see a pothole in the road, we shift to the side to avoid it. So how can we take that same aspect and apply it to our projects? Therein lies the beauty of asynchronous code.

In the past, Javascript developers had to rely primarily on callbacks or additional libraries to east the pain of “callback hell” when making external API requests. And, while callbacks may still have a place in your codebase when making local requests or awaiting a function to finish executing – wouldn’t it be great if we had a more structured and reliable way of retrieving and processing data asynchronously from an external source? We do, and they’re called promises.

To keep things neat, I’ll show some examples of how to utilize promises using the jQuery.ajax() method. In recent versions of jQuery, the objects returned by this method have an implementation of the promise interface and will make these methods a bit easier to show off. If desired though, a native asynchronous request could be wrapped in a new Promise() function with similar results.

Let’s dive right in and make an AJAX GET request. For illustration purposes, I’ll use the GitHub API results for my account.

let alertMessage;
let getGithub = $.ajax({
  method: 'GET',
  url: 'https://api.github.com/users/leftynaut',
  success: function (response) {
    alertMessage = response.location;
  }
});

console.log('Location: ' + alertMessage);

Now, we’ve already made our first asynchronous request and we have our getGithub variable referencing that response. But, before we made that call, we set created a variable called alertMessage, and then after we made the request, we asked for the console to log what should be my current location of ‘Austin, TX’. So is that what’s going to log to the console? Not without a promise it won’t.

Once again, our AJAX call is an asynchronous request. So although the console.log function is called below it in our code, that function isn’t going to wait to execute while our app is making a request to the GitHub API. So it will run before our alertMessage variable has been defined, and we’ll see Location: undefined logged to the console.

So how can we wait until our location has been passed into the alertMessage variable before we call an alert? With a promise. Our getGithub variable has a promise method attached to it called .then(). This method is going to accept two arguments, one callback function which will resolve on a successful call, and an (optional) one for a rejected call. The beauty here is that whether your call succeeds or fails – we’re waiting for the response before we continue.

Speaking of calls, a phone call is a great way to visualize this. Imagine a phone call between yourself and a friend, Roger, where important information is discussed. You want to call another friend, Shirley, but you can’t until you’ve received all of the pertinent information from Roger and you’ve disconnected with him. After this occurs, you are then able to call Shirley – but not a moment sooner. Promises work similarly – they will wait until the data has fully resolved (or failed) before they proceed.

So if we were to use a .then() method on our previous example, it would look like this:

getGithub.then(function(){
  console.log("Location: " + alertMessage);
});

Now, we would successfully get the console to display the location we were hoping for. If we wanted, we could pass in a second parameter to our .then() in the form of another callback function to catch any errors thrown by our original getGithub promise function.

Where promises really shine though is in their ability to chain promises. This way, you can ensure that asynchronous calls have the needed info before they proceed to the next call, which then will ensure it has the needed info, and so on…

Let’s see an example of this in action:

var githubAPI = 'https://api.github.com/users/leftynaut';

function getGithubLocation(githubProfile) {
  return $.ajax({
    method: 'GET',
    url: githubProfile
  });
}

function getCoordinates(location) {
  let coordinatesAPI = `http://free.gisgraphy.com/geocoding/geocode?address=${location.location}&format=JSON&from=1&to=10&indent=false`;
  return $.ajax({
    method: 'GET',
    url: coordinatesAPI,
    dataType: 'jsonp'
  });
}

function getSunrise(coordinates) {
  let sunriseAPI = `http://api.sunrise-sunset.org/json?lat=${coordinates.result[0].lat}&lng=${coordinates.result[0].lng}`;
  return $.ajax({
    method: 'GET',
    url: sunriseAPI
  });
}

function consoleSunrise(data) {
  console.log(data.results.sunrise);
}

getGithubLocation(githubAPI)
  .then(getCoordinates)
  .then(getSunrise)
  .then(consoleSunrise)

In this example, we’re making three asynchronous AJAX requests. First, we’re creating a function to get my GitHub data. Next, we create a function that passes my location of ‘Austin, TX’ to an API which will convert that string to GPS coordinates. After that, we create a function that will take those coordinates, and pass them to an API which will return the sunrise information for that location. And finally, we pass that string into a function that will print the time to the console. Thanks to promise chaining, we’re then able to link all of those functions together in a neatly structured call.

Goodbye Callback Hell.

Time Complexity and Logarithmic Bar Tricks

In the past couple of days, we have dived deep into data structures and time complexity. Learning the intricacies of computer science has been a rewarding challenge – and has resulted in quite a few “aha” moments. My personal favorite thus far has been binary search trees – especially realizing just how quickly a computer can find a value using an algorithm based on logarithmic complexity. But, even more interesting was realizing that a human can pull that off too. Let’s call it a logarithmic bar trick.

  1. Tell someone you can guess a number between 1 and 1,000,000 in twenty or less guesses, provided they let you know whether your guess is high or low
  2. Use an algorithm of logarithmic complexity O(log n) to guess
  3. ?????
  4. Profit

How does that work exactly? Every time you guess, you’re breaking down the original sample size by 50%. So your first guess is going to be 500,000. They tell you it’s higher. Your second guess is 750,000. They tell you it’s higher. At this point you’ve only made two guesses and you’ve already eliminated 75% of the possibilities. Keep up with this method, and you’ll have their number in twenty guesses tops.

Let’s see how that would look in Javascript.

var min = 1;
var max = 1000000;
var guess;
var number = Math.floor(Math.random() * max) + min;
var counter = 0;

while (guess !== number){
        counter += 1;
	guess = Math.floor((min + max) / 2);
	console.log('Guess #' + counter + ':', guess);
	if (number > guess){
		min = guess + 1;
		console.log('Number is higher');
	} else if (number < guess) {
		max = guess - 1;
		console.log('Number is lower');
	}
}

console.log('Number:',number);

First, we set our min and max variables. Then, we'll create a variable to hold our guesses called guess. Next, we'll set a number variable to a random integer between our min and max. And lastly, I want to keep track of how many guesses it's going to take to find the number, so let's create a counter variable and set it to 0.

Then, we build a while loop which will continue to run until our guess variable is equal to our number variable.

Inside of our loop, we first increment our counter variable. Next, we set the guess variable equal to to the average of the min and the max combined.

Next, we setup an if statement that's going to check whether our guess variable is higher or lower than the number. If our guess is too high, we're going to set our max variable to one less than the current guess. If it's too low, we'll set the mix variable to one more than the current guess. That's all there is to it.

For fun, I went ahead and wrapped this in a function, dropped the function call in a for loop that ran 10,000 times, and pushed the counter results to an object after each run. When only running it once, I rarely would see the algorithm find the number in less than 16 guesses. But, when running it 10,000 times, I was able to catch the program guessing correctly on the first try at least once.

Want to up the ante? Tell your friend you can guess a number between 1 and 1,000,000,000 in thirty or less guesses. Thirty? Yup. Just take your maximum number and continually divide by 2 until you hit one or less. The amount of times it takes you to get there is equal to the maximum amount of guesses needed.

1,000,000,000 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 / 2 = 0.93

Helpful links:

Moving the Needle

While my experience with Free Code Camp, Treehouse, and countless other virtual learning platforms have provided me with a great foundation in web development, I decided that I wanted to stop permitting this passion to only thrive in my spare time. Thus, I have chosen a path that allows me live, eat, and breathe software engineering all day, every day, for the rest of the year. I have recently joined cohort #47 at Hack Reactor ATX (formerly MakerSquare). Currently, I am only a few hours into day three and here’s what we’ve already covered:

  • Scopes
  • Closures
  • “This”
  • Value vs. Reference
  • Debugging
  • Data Structures (Stack & Queue)
  • Prototype Chains
  • Complexity Analysis

It has already been a real challenge during some pieces, but the opportunities to learn from those bumps in the road have already been tremendous.

Building a URL Shortener with MongoDB, Express, and Node.js

Personally, it wasn’t until I had done a few laps around Node.js until I finally felt like I had got my head around what it was capable of. So when I started the URL Shortener Microservice project, I should have expected a similar struggle for my first MongoDB application. But I didn’t.

When I had first tested the waters of learnyoumongo, I immediately felt I was in over my head. I had very little prior experience working with databases, so I took a step back and began to research the fundamentals a bit further. After I felt comfortable with databases, I took a few SQL courses to familiarize myself with relational databases. Next, I dived back into MongoDB with some great tutorials via Treehouse and Code School. At this point, I felt comfortable with the basics of querying and inserting with MongoDB, but the next step of incorporating the M into the MEAN stack was my next challenge. After a failed attempt to translate coligo’s tutorial into an API, I started from scratch.

That was the best decision I had made yet. Tackling this project step-by-step reminded me that this was the best way to learn, one small step at a time. And now that I’ve finished this project, I’m going to walk through the build process one more time. I hope this tutorial is helpful, and if anyone has any questions, comments, or critiques, please feel free to share them.

First, go ahead and initialize a new git repo (I’m going to call mine url-shortener-microservice), jump into it, and setup a directory to test out our database –
git init url-shortener-microservice
cd url-shortener-microservice

Next, setup your project’s npm and fill in any information you find necessary. I’m just going to roll through and leave all the options as their default.
npm init

Now, let’s use express-generator to scaffold our app quickly. If you get a warning about the destination not being empty, just type y to continue. If you haven’t used express-generator before, you’ll need to first install it globally.
express
npm install

Also, let’s create a .gitignore file to stop tracking the node_modules folder
echo node_modules > .gitignore

And for the final piece of the setup, let’s install all of the additional npm packages we’re going to need for this project
npm install mongodb --save
npm install shortid --save
npm install valid-url --save

Go ahead and run your app and connect to localhost:3000 in your browser. You should be seeing “Welcome to Express”. If you don’t have nodemon installed, you’ll want to install that globally too.
nodemon app

welcome-to-express

Now, startup your MongoDB daemon
mongod

Let’s setup our database and collection. Open a third tab on Terminal and run mongo. Then, we’ll create a database called url-shortener-microservice.
mongo
use url-shortener-microservice

Okay this time, we’re actually done with the setup.

Open up your routes/index.js file. I’m not going to touch on building out your / route, that’ll be up to you. So, let’s do some importing of modules. First and foremost, you’re going to need to import MongoDB. Then, import the shortid module. This will help us generate unique links for each url we pass through. And finally, import the valid-url module. As the name implies, we’re going to use that to verify that our urls are formatted properly.

var mongodb = require('mongodb');
var shortid = require('shortid');
var validUrl = require('valid-url');

Alright let’s finally get to the code here. First, we’re going to work on the creation of new links. Create a new GET route that looks like this:

router.get('/new/:url(*)', function (req, res, next) {
});

The (*) piece in our :url(*) parameter will allow us to pass in properly formatted links. Without it, Express will get confused with the forward slashes in URLs and think they’re additional parts of the route. You can also use regular expressions to accomplish this.

Let’s pause here and make sure everything is still working properly. Drop a console.log into your new route that utilizes the request parameter and test it out. My code looks like this so far:

router.get('/new/:url(*)', function (req, res, next) {
  res.send(req.params.url);
});

And when I try to access http://localhost:3000/new/http://www.lefkowitz.me in my browser, I see http://www.lefkowitz.me in the browser.

Alright. So far so good.

Now, let’s get our connection to our local MongoDB database up and running. We’ll create a variable underneath where we imported our MongoDB module at the top in order to store our connection information. I’m going to call my variable mLab, as the database will eventually need to move to the cloud and I’m going to use mLab’s free offering to host it. Also, create a variable called MongoClient to host MongoDB’s connect command.
var mLab = "mongodb://localhost:27017/url-shortener-microservice";
var MongoClient = mongodb.MongoClient

Then, back in our recently created route, replace the console.log we created with the following:

MongoClient.connect(mLab, function (err, db) {
  if (err) {
    console.log("Unable to connect to server", err);
  } else {
    console.log("Connected to server")
  };
});

Now, whenever this route is accessed, MongoDB will connect to our local database and print a message to the console.

Alright, jump below the successful connection console.log in your else statement and create two more variables. The first will set up our collection and make it a bit easier to access, and the second will be set to our url parameter.

var collection = db.collection('links');
var params = req.params.url;

Now, we’re going to create the function that imports a link to the database and returns a short link. We’ll call it newLink and it will accept a callback that will close the database connection once it’s run.

var newLink = function (db, callback) {
};

newLink(db, function () {
  db.close();
});

Okay it’s been a while since we’ve run any tests, so let’s see if we’re on track so far by importing some documents into our links collection. Inside of our newLink function, insert the following:

var insertLink = { url: params, short: "test" };
collection.insert([insertLink]);
res.send(params);

This will create a new object with our passed-thru parameters set to the url key, and “test” set to the short key. Then, it will push that object into a document in our database. And finally, we’re going to send our URL parameter to output again, just like in our last test.

Now, fire up your browser and point it to http://localhost:3000/new/http://www.lefkowitz.me

Once you see http://www.lefkowitz.me output onto the page, open up your mongo tab in Terminal and type db.links.find(). You should see something like this:

{
  "_id": ObjectId("572a780bcf012a51ee123b3b"),
  "url": "http://www.lefkowitz.me",
  "short": "test"
}
Fetched 1 record(s) in 7ms

Tip – To make working in MongoDB a bit easier in Terminal, do a global install of mongo-hacker

Alright let’s keep moving. We’re going to want to do three things when a URL is passed thru as a parameter:

  1. Check if the URL is valid
  2. If it is, assign a random set of characters to it
  3. Pass the URL and the random characters into our collection

So first, create an if/else statement utilizing our valid-url module in the newLink function. Replace the three lines we dropped in there during our last test.

if (validUrl.isUri(params)) {
  // if URL is valid, do this
} else {
  // if URL is invalid, do this
};

If a URL is valid, generate a short code. Then, create a new object. Insert that object into the collection as a new document like we did in our test. And finally, let’s push some JSON to our browser.

var shortCode = shortid.generate();
var newUrl = { url: params, short: shortCode };
collection.insert([newUrl]);
res.json({ original_url: params, short_url: "localhost:3000/" + shortCode });

If the URL isn’t valid, make sure to output an error.
res.json({ error: "Wrong url format, make sure you have a valid protocol and real site." });

Currently, this is what our index.js file should look like. Hopefully yours looks the same and you’re successfully pushing new links into your database. We’re halfway through the meat of this project!

Now, let’s look into redirection. We’re going to set up another route that once again connects to our database, runs a function, and closes the database once that function has run. The bulk of it will look similar to our last route:

router.get('/:short', function (req, res, next) {

  MongoClient.connect(mLab, function (err, db) {
    if (err) {
      console.log("Unable to connect to server", err);
    } else {
      console.log("Connected to server")

      var collection = db.collection('links');
      var params = req.params.short;

      var findLink = function (db, callback) {
      };

      findLink(db, function () {
        db.close();
      });

    };
  });
});

Now that we have that setup, we’re going to want to take the parameter that has been passed through and find it in our collection. I’m going to use the .findOne query since the short codes are unique values, we don’t want to waste resources looking for additional matches. We’re also going to limit the query to only return the url field, as all other fields are unnecessary for our needs. Our query is going to look like this:
collection.findOne({ "short": params }, { url: 1, _id: 0 })

After the query is run, we’re going to pass in a function. If a document is found, the function will return it. Once it’s returned, we’re going to use a res.redirect() to redirect the browser to the value of the returned key/value pair. If the document is not found, we’ll output another JSON error.

collection.findOne({ "short": params }, { url: 1, _id: 0 }, function (err, doc) {
  if (doc != null) {
    res.redirect(doc.url);
  } else {
    res.json({ error: "No corresponding shortlink found in the database." });
  };
});

And that’s it. We now have a functioning URL shortener! Now let’s make some tweaks to improve it. In our first route, let’s built an if/else statement that queries our database before we drop a link into it to check if that link already exists, so that we can keep the size of our database down. It will look similar to the query we just built, except this time we’re looking for the url and we’re only returning the short code. This will run at the top of the newLink function, and will be followed by an else statement that runs the original code to create a new link if the query is unsuccessful.

collection.findOne({ "url": url }, { short: 1, _id: 0 }, function (err, doc) {
  if (doc != null) {
res.json({ original_url: url, short_url: local + '/' + doc.short });

At this point, our index.js file should look like this. We’ve got a few more minor tweaks to do, and then we can move our database to mLab. First, I think having underscores and dashes as options in our short codes is a bit confusing. Underneath where we imported our shortid module, let’s set a new list of characters that replaces _ and – with $ and @.
shortid.characters('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$@');

Next, let’s make our JSON output a bit more dynamic so we don’t have to update the string when we push it to deployment. In the /new/:url(*) route, add var local = req.get('host'); + "/" above the newLink function. Then, replace the localhost:3000/ string in both JSON responses to your new local variable.

Alright, let’s move our database onto a remote server. I’m using mLab, but if you’re more comfortable with an alternative, go right ahead and use that. In mLab, hit the “Create new” button, choose “Single-node”, and then select “Sandbox”. For consistency, let’s use “url-short” as our database name. Once you’ve created your database, it’s going to ask you to create a user in order to access your database. For this example, I’ll use “user” and “pass” – but you’re probably going to want to use something a bit more secure in your app. Alright, now grab the link that’s presented and replace your mLab variable with it. Make sure to drop in your username and password in the corresponding placeholder fields.
var mLab = "mongodb://user:pass@ds015962.mlab.com:15962/url-shortener-microservice";

Now, back to the browser to see if it’s working. I’m going to attempt to access http://localhost:3000/new/http://www.lefkowitz.me again. I’m seeing a JSON response, so that’s a good sign. Now let’s hit the “Collections” tab in mLab, refresh the page, and see if our collection is there.

Yup, we have a links collection with one document in it. Success!
mlab

Before we push this to Heroku, you’re going to want to exclude your database username/password information from your Github repo. Create a file called config.js in your root directory, and paste the following into it:

var config = {};

config.db = {};

config.db.host = 'user:pass@ds015962.mlab.com:15962;
config.db.name = 'url-shortener-microservice';

module.exports = config;

Then, in your index.js file. Drop the following in between your mongodb and MongoClient variables:

var config = require('../config');
var mLab = 'mongodb://' + config.db.host + '/' + config.db.name;

Now, in your .gitignore file, add config.js. Push your code to Github, and then create a new branch called heroku and remove config.js from your .gitignore file. Push your app to Heroku, grab a beer, and pat yourself on the back.

Here’s the final code.

That’s it. My personal next steps for this project are to DRY it out a bit, create an option for custom short codes, and then dive into a dashboard with some analytics. Again, if you have any questions, comments, or critiques, please feel free to share them.

Front End Dev

Finally finished up my intermediate front end development projects and have earned my front end development certificate. I really enjoyed my time working on these tougher projects. While the algorithm projects were fun to toy with the backend of coding, these projects have enabled me to create tangible tools and games on CodePen with code that I can apply to my own ideas. I wish I had more interesting content to put on this blog, but I’m more interested in returning to coding. Up next is the advanced algorithm section, for which I know I’m going to have to beef up my regex skills to survive in.

Here are some of my favorite projects since my last post:
Zipline: Stylize Stories on Camper News
Zipline: Build a Wikipedia Viewer
Zipline: Build a Tic Tac Toe Game
Zipline: Build a Simon Game

My First API

In the past month, Free Code Camp did a major restructuring of their challenge map. One such change I noticed was the removal of the Udacity OOP course that I found particularly difficult at my level. Since then, I have gone through and ‘filled in the holes’ where new lessons have appeared. Currently I am all caught up and about to start on Upper Intermediate Algorithm Scripting. I have been jumping back-and-forth between Treehouse and Free Code Camp, as I find the lessons on the former are strongest, while the practice excels on the latter. Working with CodePen has been great, the immediate feedback in the preview window is incredibly powerful. My favorite project by far was working with the Twitch.tv API. It was really enjoyable to see my code interact with another website. I look forward to toying with more APIs in the future.

Zipline: Build a Personal Portfolio Webpage
Zipline: Build a Random Quote Machine
Zipline: Show the Local Weather
Zipline: Build a Pomodoro Clock
Zipline: Use the Twitch.tv JSON API

Right now I’m working through a Node.js lesson on Treehouse. Back I go.

First Round of Bonfires (Basic Algorithm Scripting) Complete

At the beginning, 800 hours of practice seemed like it was going to take me 400, as my previous experience had me rolling through the first half of training in only a matter of weeks. Then I arrived at the Basic Algorithm Scripting section of bonfires and some of them were a bit of a struggle. But after a couple of pair programming sessions, questions in the chat rooms, Google and Stack Overflow searches, and a lot of trial and error, I am now past that stage. As much as I’ve been wanting to keep up with this blog and a redesign of my personal site, I’d rather just get back to camp. Here is a dump of all of my bonfires thus far (minus the first couple that I forgot to save, which unfortunately Free Code Camp doesn’t do for you). Hopefully these can give hints to others as they progress through camp.
Bonfire: Factorialize a Number
Bonfire: Check for Palindromes
Bonfire: Find the Longest Word in a String
Bonfire: Title Case a Sentence
Bonfire: Return Largest Numbers in Arrays
Bonfire: Confirm the Ending
Bonfire: Repeat a string repeat a string
Bonfire: Truncate a string
Bonfire: Chunky Monkey
Bonfire: Slasher Flick
Bonfire: Mutations
Bonfire: Falsey Bouncer
Bonfire: Where art thou
Bonfire: Seek and Destroy
Bonfire: Where do I belong
Bonfire: Sum All Numbers in a Range
Bonfire: Diff Two Arrays
Bonfire: Roman Numeral Converter
Bonfire: Search and Replace
Bonfire: Pig Latin
Bonfire: DNA Pairing
Bonfire: Missing letters
Bonfire: Boo who
Bonfire: Sorted Union
Bonfire: Convert HTML Entities
Bonfire: Spinal Tap Case
Bonfire: Sum All Odd Fibonacci Numbers
Bonfire: Sum All Primes
Bonfire: Smallest Common Multiple
Bonfire: Finders Keepers
Bonfire: Drop it
Bonfire: Steamroller
Bonfire: Binary Agents
Bonfire: Everything Be True
Bonfire: Arguments Optional

Copyright © 2017 Thoughts

Theme by Anders NorenUp ↑