Share
Explore

JavaScript Functions, Objects, and working with MONGO DB

Learning Outcomes:

JavaScript functions - the six javaScript function types: explain promises and async/await, anonymous functions, and arrow functions.
Show how JavaScript Objects are just functions.
Learn how to use Asych / Await for accessing MONGODB

JavaScript Function Workbook

Overview

This workbook is designed to guide you through learning the six types of functions in JavaScript: Regular functions, Method functions, Constructor functions, Anonymous functions, Arrow functions, and IIFE (Immediately Invoked Function Expressions). We will also delve into concepts like Promises and async/await, and illustrate how JavaScript Objects are essentially functions.

Lesson 1: Regular Functions

In JavaScript, a function is a reusable set of instructions. You define it once, and then you can call it from anywhere in your code.

function greet(name) {
console.log("Hello, " + name);
}

Exercise 1

Create a function that takes two numbers as arguments and returns their sum.

Lesson 2: Method Functions

Methods are functions that are properties of an object. Here's an example:
javascriptCopy code
let person = {
firstName: "John",
lastName: "Doe",
fullName: function() {
return this.firstName + " " + this.lastName;
}
};

Exercise 2

Create an object representing a book, with properties title, author, and a method called getDetails that returns a string containing both.

Lesson 3: Constructor Functions

JavaScript constructors are special functions that can be used to instantiate new objects with methods and properties defined by that function.

function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}

Exercise 3

Create a constructor function for a Student object. The object should have properties for firstName, lastName, id and a method to display full name.

Lesson 4: Anonymous Functions

Anonymous functions are functions that were declared without any named identifier to refer to it. They are commonly used as arguments to other functions or as immediately invoked function expressions.

let array = [1, 2, 3];
array.map(function(item) {
return item * 2;
});

Exercise 4

Use an anonymous function within the Array.filter method to get all even numbers from an array.

Here is the complete code solution using an anonymous function within the Array.filter method to get all even numbers from an array:
javascriptCopy code
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

let evenNumbers = numbers.filter(function(number) {
return number % 2 === 0;
});

console.log(evenNumbers); // [2, 4, 6, 8, 10]

In this solution, we start with an array of numbers. We use the Array.filter method to create a new array that contains only the elements of the original array that pass a test. The test is defined by an anonymous function that we pass to Array.filter. This function takes a number as an argument, and returns true if the number is even, and false otherwise. The Array.filter method calls this function for each element in the original array, and constructs the new array from the elements for which the function returns true.

Lesson 5: Arrow Functions

Arrow functions allow for a shorter syntax when writing functions. They are anonymous and change the way this binds in functions.
javascriptCopy code
const add = (a, b) => a + b;

Exercise 5

Rewrite the anonymous function from Exercise 4 using an arrow function.
The arrow function version of the previous example would look like this:
javascriptCopy code
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

let evenNumbers = numbers.filter(number => number % 2 === 0);

console.log(evenNumbers); // [2, 4, 6, 8, 10]

In this example, the function passed to filter has been replaced by an arrow function. Arrow functions provide a more concise syntax for defining functions in JavaScript. The arrow (=>) separates the function's parameters from its body. In this case, the arrow function takes one parameter, number, and returns number % 2 === 0.

Lesson 6: IIFE (Immediately Invoked Function Expression)

An IIFE is a function that runs as soon as it is defined.
javascriptCopy code
(function() {
var x = "Hello"; // I will invoke myself
console.log(x);
})();

Exercise 6

Write an IIFE that concatenates two strings and outputs the result to the console.
Here is the solution for creating an Immediately Invoked Function Expression (IIFE) that concatenates two strings and outputs the result to the console:
javascriptCopy code
(function() {
let string1 = "Hello, ";
let string2 = "World!";
let result = string1 + string2;

console.log(result); // Outputs: "Hello, World!"
})();

In this example, an anonymous function is defined and then immediately invoked. The function concatenates the strings "Hello, " and "World!" and then logs the result to the console. Because this is an IIFE, the function executes as soon as it is defined.

Lesson 7: Promises and async/await

A Promise is an object representing the eventual completion or failure of an asynchronous operation. Async/await syntax is a cleaner way of working with promises.
javascriptCopy code
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});

// Async/Await version
async function asyncCall() {
console.log('calling');
var result = await promise;
console.log(result);
}

asyncCall();

Exercise 7

Create a Promise that resolves after 2 seconds and returns the string "Hello". Use async/await to handle the Promise.

How to create a Promise that resolves after 2 seconds and returns the string "Hello", using async/await to handle the Promise:
javascriptCopy code
// Create a promise that resolves after 2 seconds
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("Hello"), 2000);
});

// Async function to handle the promise
async function asyncCall() {
console.log('calling');
var result = await promise;
console.log(result); // outputs: 'Hello'
}

// Invoke the async function
asyncCall();

In this example, the asyncCall function is declared as async, meaning it returns a Promise. Within this function, we use the await keyword to pause execution of the function until the Promise promise is resolved. The resolved value of the Promise is then logged to the console.

Lesson 8: JavaScript Objects as Functions

In JavaScript, functions are objects. You can therefore attach properties and methods to a function object and treat it like any other object.
javascriptCopy code
function greet() {
console.log('Hello, World!');
}

greet.language = 'English';
console.log(greet.language);

Exercise 8

Create a function addNumbers that adds two numbers. Add a property description to the addNumbers function and set it to "This function adds two numbers". Log addNumbers.description to the console.

Here's the code to create a function addNumbers that adds two numbers, add a property description to the addNumbers function, and log addNumbers.description to the console:
javascriptCopy code
function addNumbers(a, b) {
return a + b;
}

addNumbers.description = "This function adds two numbers";

console.log(addNumbers.description); // Outputs: "This function adds two numbers"

In this example, we first define a simple function addNumbers that takes two arguments and returns their sum. Then, we add a description property to the addNumbers function and set its value to the string "This function adds two numbers". Finally, we log addNumbers.description to the console, which outputs the string we assigned to it.

Lesson 9: Using Promises with MongoDB and Node.js

MongoDB is a document-based database that is often used in web development. Node.js provides a powerful environment for server-side JavaScript, and MongoDB has built a driver specifically for Node.js. This driver provides a way to interact with MongoDB using Promises.
When interacting with MongoDB, we often need to wait for operations like finding, inserting, updating, or deleting documents to complete before we can proceed with our code. Promises can help us manage this asynchronous behavior.
Here's an example:
javascriptCopy code
const MongoClient = require('mongodb').MongoClient;
const url = 'mongodb://localhost:27017';
const dbName = 'myproject';

async function run() {
let client;

try {
client = await MongoClient.connect(url);
console.log("Connected correctly to server");

const db = client.db(dbName);

// Insert a single document
let r = await db.collection('inserts').insertOne({a:1});
assert.equal(1, r.insertedCount);

// Find all documents
let docs = await db.collection('inserts').find({}).toArray();
console.log(docs);

} catch (err) {
console.log(err.stack);
}

// Close connection
if (client) {
client.close();
}
}

run().catch(console.dir);

In this example, we connect to a MongoDB database, insert a document, find all documents, and finally close the connection. Each step waits for the previous one to complete because of the await keyword in front of the Promise-returning functions.

Exercise 9

Connect to a local MongoDB database named 'test'.
Insert a new document with any data you want into a collection named 'workbook'.
Find all documents in the 'workbook' collection and log them to the console.
Remember to handle any errors and to close the connection when you're done.
Here's a possible solution using MongoDB's Node.js driver:
javascriptCopy code
const MongoClient = require('mongodb').MongoClient;

async function run() {
const client = new MongoClient('mongodb://localhost:27017', { useUnifiedTopology: true });
try {
// Connect to the MongoDB server
await client.connect();

// Connect to the 'test' database
const db = client.db('test');

// Insert a new document into the 'workbook' collection
await db.collection('workbook').insertOne({
title: "JavaScript Workbook",
description: "A workbook for learning JavaScript",
topics: ["functions", "promises", "async/await"]
});

// Find all documents in the 'workbook' collection
const documents = await db.collection('workbook').find({}).toArray();

// Log the documents to the console
console.log(documents);
} catch (err) {
// Log any errors that occurred
console.error(err);
} finally {
// Close the connection to the MongoDB server
await client.close();
}
}

run();

In this solution, an async function run is defined that connects to a MongoDB server, inserts a document into the 'workbook' collection of the 'test' database, fetches all documents from the 'workbook' collection, logs them to the console, and then closes the connection. Errors are caught and logged, and the connection is closed even if an error occurs.

Lesson 10: CRUD Operations with MongoDB and Promises

Let's go deeper with CRUD (Create, Read, Update, Delete) operations. For these operations, we can use insertOne(), findOne(), updateOne(), and deleteOne(), respectively. All these methods return a Promise.
Here's an example:
javascriptCopy code
async function run() {
let client;

try {
client = await MongoClient.connect(url);
console.log("Connected correctly to server");

const db = client.db(dbName);
const collection = db.collection('documents');

// Insert a document
let r = await collection.insertOne({title: 'New Document'});

// Find a document
let doc = await collection.findOne({title: 'New Document'});
console.log(doc);

// Update the document
r = await collection.updateOne({title: 'New Document'}, {$set: {title: 'Updated Document'}});
console.log(r.modifiedCount);

// Delete the document
r = await collection.deleteOne({title: 'Updated Document'});
console.log(r.deletedCount);

} catch (err) {
console.log(err.stack);
}

// Close connection
if (client) {
client.close();
}
}

run().catch(console.dir);

Exercise 10

Connect to a local MongoDB database named 'workbook'.
Insert a new document into a collection named 'documents'.
Find the inserted document and log it to the console.
Update the document you just inserted.
Delete the updated document.
Make sure to handle errors and close the connection when you're done.
Remember, as we're using Promises and async/await, any errors that happen inside an async function will be thrown as a rejected Promise. We can catch these with .catch() at the end of our async function calls.

Solution using the MongoDB Node.js driver. The steps will be explained in comments inline with the code:
javascriptCopy code
const MongoClient = require('mongodb').MongoClient;

async function run() {
const client = new MongoClient('mongodb://localhost:27017', { useUnifiedTopology: true });
try {
// Connect to the MongoDB server
await client.connect();

// Connect to the 'workbook' database
const db = client.db('workbook');

// Insert a new document into the 'documents' collection
const result = await db.collection('documents').insertOne({
title: "New Document",
content: "This is a new document for exercise 10."
});
console.log("Document inserted with _id: " + result.insertedId);

// Find the inserted document and log it to the console
const insertedDocument = await db.collection('documents').findOne({ _id: result.insertedId });
console.log("Inserted document: ", insertedDocument);

// Update the document you just inserted
const updateResult = await db.collection('documents').updateOne({ _id: result.insertedId }, { $set: { title: "Updated Document" } });
console.log("Number of documents matched and modified: ", updateResult.matchedCount, updateResult.modifiedCount);

// Delete the updated document
const deleteResult = await db.collection('documents').deleteOne({ _id: result.insertedId });
console.log("Number of documents deleted: ", deleteResult.deletedCount);
} catch (err) {
// Log any errors that occurred
console.error(err);
} finally {
// Close the connection to the MongoDB server
await client.close();
}
}

run();

In this example, the async function run does all the required operations. It starts by connecting to a MongoDB server and accessing the 'workbook' database. It inserts a new document into the 'documents' collection, finds and logs this document, updates the document's title, deletes it, and finally, closes the connection to the server. All errors are logged, and the connection is closed even if an error occurs.
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.