Simple Web API & Client

Background
The language of the web is JavaScript, and being fluent in it will only come with practice.
The majority of my background has been in the gaming realm, mainly focused around Unity and C# building prototypes with no restrictions in mind. However, in the web world, one doesn’t have all the resources compared to a natively running game/app. Since I’ve been using a lot of JavaScript and TypeScript at work, I decided to expand my knowledge using some tech I hadn’t tinkered with before.
Goals
Create a simple, end-to-end web application that incorporates your typical client and server tech stack. In short, build a CRUD app — the world famous Todo list app.
Front-end
- Super simple, vanilla JavaScript
- Use async/await or Promises for asynchronous operations
- MVC design pattern
Back-end
- NodeJS
- Express server
- MongoDB + Mongoose
- MVC design pattern
Development
Tools and products used
- GitLab
- Cmder
- Visual Studio Code
- Docker
Visual Studio Code extensions
- jshint
- Beautify
- Debugger for Chrome
- Bracket Pair Colorizer
- Docker
Back-end
I followed this article as a reference, as it very neatly laid out the basics and structure of exactly what I wanted to build.
I made the following changes/additions:
- Specifying a CORS policy
- Detailed comments to help my understanding
- Removed hard-coded strings and replaced them with a Constants class
- Removed duplicate code
- Used a Docker container to run MongoDB instead of installing it locally
- Used JSHint for linting
Setting up MongoDB
MongoDB is a document based (JSON) distributed database built for modern apps and popular in the web realm. It was lightweight and easy enough to get started with.
Instead of opting to install it on my PC, I decided to use the mighty Docker instead! I’d recently fallen in love with Docker after using it to set up an ownCloud instance, a few nginx containers, and Traefik (for reverse proxying).
-
Step 1: Install Docker Desktop for your Windows/OSX/Linux.
-
Step 2: Find the MongoDB official image on Docker Hub.

-
Step 3: You’ll notice there are various images for many different versions of MongoDB — we can choose
3.4-xenial:Open up a terminal/command line and run:
docker run --name restful-api-mongo -d -p 27017-27019:27017-27019 mongo:3.4-xenialLet’s understand what’s going on in that one line:
--name restful-api-mongo— create a new container restful-api-mongo-d— run in detached mode (i.e. it will run in the background even after you close the terminal window)-p— specifies which port we want to map to. The mapping isHOST_PORT:CONTAINER_PORT, so we’re mapping the range 27017-27019 from the host machine to the container’s ports 27017-27019.mongo:3.4-xenial— specifying the image name (mongo) and its version (3.4-xenial)
Docker will then pull the image (if it’s not already cached on your machine), then start it. If it was successful, you should just see the container id displayed.
-
Step 4: Run
docker ps— and you should see something like this:
Now that Mongo is set up and running, I can start the webserver.
Project structure

Since we’re using an MVC pattern, the classes are separated accordingly:
todoListController.js: Central controller that provides the functionality by making use of the view and model. It contains the functions that retrieve the data from the model and process it accordingly.todoListModel.js: Makes use of Mongoose, which gives us neat MongoDB object modeling. Contains theSchema, which allows us to do JSON schema validation.todoListRoutes.js: Defines the specific routes for each operation. The instance ofexpressis passed to it so it can set these routes on it using.route.constants.js: Contains constants used throughout the code.server.js: Entry point to the API. Defines the CORS policy, connects to Mongo via Mongoose, makes use ofbodyParserfor parsing incoming request bodies in middleware before the handlers (allowing us to access the body viarequest.body), and starts theexpressserver.
Front-end
Keeping it simple and focusing only on the basic CRUD operations, I used plain JavaScript for the front-end, using TodoMVC as a starting point.
Asynchronous operations
Since we’ll be fetching data from the server via the Web API, we need to do this in an asynchronous manner — i.e. when we request something, the response is not instantaneous, so we must wait for the response to come back and handle it once it’s returned.
I looked at the differences between async/await vs Promises and opted for Promises. I did later read in this article that async/await outperforms Promises. Perhaps I’ll try using async/await in the next project.
I made use of the fetch API to handle all requests sent to the webserver.
Project Structure

controller.js: Accepts theviewandmodelas parameters when instantiated. Binds onto the view or model — instead of using.bindI used arrow functions since they preservethis. Serves as the main controller between the model and view; data is passed down to the view/model, and it listens for events coming up from them.model.js: Handles all operations related to the model (data) from the back-end. Maintains an array with all the task records from the server. Uses a helper,db.js, to facilitate all calls.task.js: Meant to serve as the model (type) which is a representation of each record, though I haven’t used it yet — this will be used in the future, perhaps when I convert this project into TypeScript.constants.js: Stores all constants.db.js: Provides functions to interact with the API. This is where the actualfetchAPI calls are performed.view.js: Responsible for all DOM interactions. Binds functions to the controller and acts on data it receives from the controller.app.js: Entry point for the client.
Usage
Start the following in this order:
- The MongoDB container via Docker
- The Web API
- The front-end
Result
