0% found this document useful (0 votes)
14 views38 pages

Dom Promises Modules

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views38 pages

Dom Promises Modules

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 38

DOM

Definition: JavaScript to program the behavior of web pages

The src atribute


<script src="./exampleScript.js"></script>
The <script> above would look for a file
called exampleScript.js that is in the same folder/directory as
our index.html file.

Select and Modify Elements


The .querySelector() method allows us to specify a CSS selector
and then returns the first element that matches that selector.
The following code would return the first paragraph in the document.

document.querySelector('p');
You can also use other CSS selectors such as an element’s . class or
its # ID.

Another option, if you want to access elements directly by their id,


you can use the aptly named .getElementById() method:

document.getElementById('bio').innerHTML = 'The
description';
The example chains so that it selects the element with an ID of ‘bio’
and sets its .innerHTML to the text 'The description'.

Style an element
For example, the following code selects the first element with
a class of blue and assigns blue as the background-color:

let blueElement = document.querySelector('.blue');


blueElement.style.backgroundColor = 'blue';
Unlike CSS, the DOM style property does not implement a hyphen
such as background-color, but rather camel case
notation backgroundColor. The following chaining syntax would also
work:

document.querySelector('.blue').style.fontFamily
= 'Roboto';

Defer attribute
The defer attribute specifies scripts should be executed after
the HTML file is completely parsed. When the HTML parser
encounters a <script> element with the defer attribute, it loads the
script but defers the actual execution of the JavaScript until after it
finishes parsing the rest of the elements in the HTML file.

Here is an example of the defer tag:

<script src="example.js" defer></script>

Async attribute
The async attribute loads and executes the script
asynchronously with the rest of the webpage. This means that,
similar to the defer attribute, the HTML parser will continue parsing
the rest of the HTML as the script is downloaded in the background.
However, with the async attribute, the script will not wait until the
entire page is parsed: it will execute immediately after it has been
downloaded. Here is an example of the async tag:

<script src="example.js" async></script>

getElementsByClassName getElementsByTagName
The .getElementsByClassName() and .getElementsByTagName() m
ethods which return an array of elements, instead of just one
element. You can use bracket notation to access individual elements
of an array:

// Set first element of .student class as 'Not yet


registered'
document.getElementsByClassName('student')[0].innerHTML
= 'Not yet registered';

// Set second <li> tag as 'Cedric Diggory'


document.getElementsByTagName('li')[1].innerHTML = 'Cedric
Diggory`;

Traversing the DOM


<ul id='groceries'>
<li id='must-have'>Toilet Paper</li>
<li>Apples</li>
<li>Chocolate</li>
<li>Dumplings</li>
</ul>
let parentElement = document.getElementById('must-
have').parentNode; // returns <ul> element
let childElements
= document.getElementById('groceries').children; //
returns an array of <li> elements
EXEMPLO:

let first = document.body.children[0].innerHTML = 'BROWN BEARS ARE


AWESOME!'

Create Elements
However, it does not append it to the document. It creates an empty
element with no inner HTML.

let paragraph = document.createElement('p');

We can assign values to the properties of the newly created element


like how we’ve done previously with existing elements.

paragraph.id = 'info';
paragraph.innerHTML = 'The text inside the paragraph';
Above, we use the .id property to assign 'info' as ID and
the .innerHTML property to set 'The text inside the
paragraph' as the content of the <p> element.

Insert Elements
The following code appends the <p> element stored in
the paragraph variable to the document body.

document.body.appendChild(paragraph);

The .appendChild() method does not replace the content inside of


the parent, in this case, body. Rather, it appends the new element
as the last child of that parent.

Remove an Element
let paragraph = document.querySelector('p');
document.body.removeChild(paragraph);

This removes the first paragraph from the document body.


If you want to hide an element rather than completely
deleting it, the .hidden property allows you to hide it by setting
the property as true or false:

document.getElementById('sign').hidden = true;

Add Click Interactivity

let element = document.querySelector('button');

element.onclick = function() {
element.style.backgroundColor = 'blue'
};
You can also assign the .onclick property to a function by name:

let element = document.querySelector('button');

function turnBlue() {
element.style.backgroundColor = 'blue';
}
element.onclick = turnBlue;

Event Handler Registration

let eventTarget
= document.getElementById('targetElement');

eventTarget.addEventListener('click', function() {
// this block of code will run when click event happens
on eventTarget element
});

Instead of using an anonymous function as the event handler, it’s


best practice to create a named event handler function. Your code will
remain organized and reusable this way, even if your code gets
complex.

function eventHandlerFunction() {
// this block of code will run when click event happens
}
eventTarget.addEventListener('click',
eventHandlerFunction);
Removing Event Handlers

This method stops the event target from “listening” for an event to
fire when it no longer needs to. .removeEventListener() also takes two
arguments:

eventTarget.removeEventListener('click',
eventHandlerFunction);

Because there can be multiple event handler functions associated


with a particular event, .removeEventListener() needs both the exact
event type name and the name of the event handler you want to
remove. If .addEventListener() was provided an anonymous function,
then that event listener cannot be removed.

EX:

let fortunes = ["A beautiful, smart, and loving person will be comi
ng into your life.",
"A fresh start will put you on your way.",
"A golden egg of opportunity falls into your lap this month.",
"A smile is your personal welcome mat.",
"All your hard work will soon pay off."
]
let button = document.getElementById('fortuneButton');
let fortune = document.getElementById('fortune');

function fortuneSelector(){
let randomFortune = Math.floor(Math.random() * fortunes.length);
return fortunes[randomFortune];
}
function showFortune(){
fortune.innerHTML = fortuneSelector();
button.innerHTML = "Come back tomorrow!";
button.style.cursor = "default";
button.removeEventListener('click', showFortune)
//add your code her
}
button.addEventListener('click', showFortune);
Event Object Properties

JavaScript stores events as Event objects with their related data and
functionalities as properties and methods. When an event is
triggered, the event object can be passed as an argument to the
event handler function.

function eventHandlerFunction(event){
console.log(event.timeStamp);
}
eventTarget.addEventListener('click',
eventHandlerFunction);

In the example above, when the 'click' event is triggered on


the eventTarget, the eventHandlerFunction receives event, the Event
object, which has information related to the 'click' event.

There are pre-determined properties associated with event objects.


You can call these properties to see information about the event, for
example:

 the .target property to reference the element that the event is


registered to.
 the .type property to access the name of the event.
 the .timeStamp property to access the number of milliseconds
that passed since the document loaded and the event was
triggered.

EX:

// This variable stores the "Pick a Color" button


let button = document.getElementById('color-button');
// This variable stores the "Mystery Color" button
let mysteryButton = document.getElementById('next-button');
// This random number function will create color codes for the rand
omColor variable
function colorValue() {
return Math.floor(Math.random() * 256);
}
function colorChange(event){
let randomColor = 'rgb(' + colorValue() + ',' + colorValue() + ',
' + colorValue() + ')';
event.target.style.backgroundColor = randomColor
}
button.addEventListener('click', colorChange)
mysteryButton.addEventListener('wheel', colorChange)
Mouse Events

You’ve seen the click and wheel events, but, are more mouse events
to explore!

The mousedown event is fired when the user presses a mouse button
down.

The mouseup event is fired when the user releases the mouse button.

The mouseover event is fired when the mouse enters the content of an
element.

The mouseout event is fired when the mouse leaves an element.

Keyboard Events

keyboard events are triggered by user interaction with keyboard keys


in the browser.

The keydown event is fired while a user presses a key down.

The keyup event is fired while a user releases a key.

The keypress event is fired when a user presses a key down and
releases it.

Keyboard events have unique properties assigned to their event


objects like the .key property that stores the values of the key pressed
by the user. You can program the event handler function to react to a
specific key, or react to any interaction with the keyboard.
------------------------------------//--------------------------
-

DEBUGGING JAVASCRIPT CODE

JavaScript Error Types

Here are three common error types:

 SyntaxError: When this error is thrown, scan your code to


make sure you properly opened and closed all brackets,
braces, and parentheses and that you didn’t include any
invalid semicolons.
 ReferenceError: This error will be thrown if you try to use a
variable that does not exist. When this error is thrown,
make sure all variables are properly declared.
 TypeError: This error will be thrown if you attempt to perform
an operation on a value of the wrong type. For example, if we
tried to use a string method on a number, it would throw
a TypeError.

Debugging Review

1. Is your code throwing errors? If so, read the error stack


trace for the type, description, and location of the error. Go to
the error’s location and try to fix.
2. Is your code broken but not throwing errors? Walk
through your code using console.log() statements. When
unexpected results occur, isolate the bug and try to fix it.
3. Did you locate the bug using steps 1 and 2, but can’t fix
the bug? Consult documentation to make sure you are using
all JavaScript functionality properly. If you are still stuck, Google
your issue and consult Stack Overflow for help. Read solutions
or post your own Stack Overflow question if none exist on the
topic.

NOTA: In the error message TypeError: students.filter is not a


function, it’s highly unlikely that someone else is having
a .filter() issue on a students variable with the same data types, so
that’s the type of thing that could be more generic. Instead of
searching for “TypeError: students.filter is not a function”,
you can try something like “TypeError: object filter() is not a
function” and add a keyword for the language. The final
search might be: “TypeError: object filter() is not a function
JavaScript”.

Handling with try...catch


We can also use a try...catch statement to handle built-in errors
that are thrown by the JavaScript engine that is reading and
evaluating our code.

const someVar = 'Cannot be reassigned';


try {
someVar = 'Still going to try';
} catch(e) {
console.log(e);
}
// Prints: TypeError: Assignment to constant variable.

Using a try...catch statement for built-in JavaScript errors is really


beneficial when we need to use data from an external source that’s
not written directly in our program.

Let’s say we expect to grab an array from a database but the


information we get back is a string. In our program, we could have a
function that only works on arrays. If that function was called with a
string instead of an array we would get an error and our program
would stop running!

However, we can use a try...catch statement to handle the thrown


error for us which allows our program to continue running and we
receive a message knowing what went wrong!

Instructions

1. In main.js there is a function capAllElements() that takes an


array of elements and capitalizes each element.
Currently, it’s written in a way the function will execute regardless of
what argument is passed in but if the argument isn’t an array, an
error is thrown and our program stops running. Run your code to see
what error shows up in the console.

Let’s handle that error:

 Put the existing arr.forEach(...) code in a try block.


 Add a catch statement after the try block and inside
the catch block log the error to the console.

------------------------------------//--------------------------
-

MODULES
module.exports
To create a module, you simply have to create a new file where the
functions can be declared. Then, to make these functions available to
other files, add them as properties to the built-
in module.exports object:

/* converters.js */
function celsiusToFahrenheit(celsius) {
return celsius * (9/5) + 32;
}

module.exports.celsiusToFahrenheit = celsiusToFahrenheit;

module.exports.fahrenheitToCelsius = function(fahrenheit) {
return (fahrenheit - 32) * (5/9);
};
The code snippet above demonstrates two ways of exporting
functions from a module. Let’s break it down:

require()
The require() function accepts a string as an argument. That string
provides the file path to the module you would like to import.

Let’s update water-limits.js such that it uses require() to import


the .celsiusToFahrenheit() method from the module.exports object
within converters.js:

/* water-limits.js */
const converters = require('./converters.js');

const freezingPointC = 0;
const boilingPointC = 100;

const freezingPointF = converters.celsiusToFahrenheit(freezingPointC);


const boilingPointF = converters.celsiusToFahrenheit(boilingPointC);

console.log(`The freezing point of water in Fahrenheit is $


{freezingPointF}`);
console.log(`The boiling point of water in Fahrenheit is $
{boilingPointF}`);

In this case, ./ is a relative path indicating that converters.js is


stored in the same folder as water-limits.js. When you use require(),
the entire module.exports object is returned and stored in the
variable converters. This means that both
the .celsiusToFahrenheit() and .fahrenheitToCelsius() methods can be
used in this program!

Using Object Destructuring to be more


Selective With require()

In many cases, modules will export a large number of functions but


only one or two of them are needed. You can use object destructuring
to extract only the needed functions.

Let’s update celsius-to-fahrenheit.js and only extract


the .celsiusToFahrenheit() method,
leaving .fahrenheitToCelsius() behind:

/* celsius-to-fahrenheit.js */
const { celsiusToFahrenheit } = require('./converters.js');

const celsiusInput = process.argv[2];


const fahrenheitValue = celsiusToFahrenheit(celsiusInput);

console.log(`${celsiusInput} degrees Celsius = ${fahrenheitValue}


degrees Fahrenheit`);
With this approach, the remainder of the program works the same
way but the program avoids importing a function it does not need.

const add = (x, y) => {


return x + y;
}
export { add };
export { add, subtract };
import { add } from './math_functions.js';

Here, import will find add in math_functions.js, import just that


function for you to use, and ignore the rest. The ./ tells the import to
look for the math_functions.js file in the same folder as the current
file. The relative file path (./) and file extension (.js) are required when
using import in this way.
You can import more than one item from the file by adding them in
the import statement like this:

import { add, subtract } from './math_functions.js';

Use * to Import Everything from a File

Suppose you have a file and you wish to import all of its contents into
the current file. This can be done with the import * as syntax

import * as myMathModule from


"./math_functions.js";Here's how you can use
the add and subtract functions that were imported:

myMathModule.add(2,3);
myMathModule.subtract(5,3);

------------------------------------//--------------------------
-

ASYNC JAVASCRIPT AND HTTP REQUESTS

What is Synchronous Code?


Consider the building of a house. We would first need to first lay down the bricks that make
our foundation. Then, we layer more bricks on top of each other, building the house from the
ground up. We can’t skip a level and expect our house to be stable. Therefore, the laying of
bricks happens synchronously, or in sequential order.

Likewise, synchronous code executes in sequential order — it starts with the code at the top
of the file and executes line by line until it gets to the end of the file. This type of behavior is
known as blocking (or blocking code) since each line of code cannot execute until the previous
line finishes.

What is Asynchronous Code?


Let’s begin again with examining a real-life scenario, like baking a cake. We could start to
preheat the oven and prepare our cake’s ingredients while we wait for our oven to heat up.
The wait for the oven and the preparation of ingredients can happen at the same time, and
thus these actions happen asynchronously.
Similarly, asynchronous code can be executed in parallel to other code that is already
running. Without the need to wait for other code to finish before executing, our apps can save
time and be more efficient. This type of behavior is considered non-blocking.

For most programming languages, the ability to execute


asynchronous code depends on the number of threads that an app
has access to. We can think of a thread as a resource that a computer
provides an app to do a task.
Thread 1: build house foundation -> build walls ->
construct floor
A single thread could work for a synchronous task like building a
house. However, in our cake baking example, our threads would have
to look like this:

Thread 1: preheat oven


Thread 2: prepare ingredients -> bake-cake

Asynchronous Code in Web Development


If we use synchronous (blocking) code in the browser, we might be stopping a user
from being able to interact with a web app until the code is done running. This isn’t a
great user experience. If our app takes a long time to load, our users might think that
something’s wrong and might even opt to browse a different site!
However, if we opt for an asynchronous approach, we can cut down on the wait
time. We’d load only the code that’s necessary for user interactions and then load up
other bits of code in the background. With asynchronous code, we can create better
user experiences and make apps that work more efficiently!

It is our job as developers to think about how much time it takes to complete a task
and how to plan around that wait. Tasks like contacting the back-end to retrieve
information, querying our database for user information, or making a request to an
external server, like a 3rd party API, take varying amounts of time. Since we aren’t sure
when we’ll get this information back, we can use asynchronous code to run these tasks
in the background.

JavaScript and Asynchronous Code


JavaScript is a single-threaded language. This means it has a single thread that can
carry out one task at a time.
Asynchronous Callbacks

This is a type of callback function that executes after a specific condition is met and runs
concurrently to any other code currently running.
easterEgg.addEventListener('click', () => {
console.log('Up, Up, Down, Down, Left, Right, Left, Right, B, A');
});

In the code above, the function passed as the second argument of .addEventListener() is an
asynchronous callback — this function doesn’t execute until the easterEgg is clicked.

setTimeout
With setTimeout() we can write code that tells our JavaScript program to wait a minimum
amount of time before executing its callback function. Take a look at this example:
setTimeout(() => {
console.log('Delay the printing of this string, please.');
}, 1000);

The setTimeout() takes 2 arguments, a callback function and a number specifying how long
to wait before executing the function. In the example above, the function will print 'Delay the
printing of this string, please.' after 1000 milliseconds (or 1 second) have passed.

Since setTimeout() is non-blocking, we can be executing multiple lines of code at the same
time!
setTimeout(() => {
console.log('Delay the printing of this string, please.');
}, 1000);
console.log('Doing important stuff.');
console.log('Still doing important stuff.');
Which outputs:

'Doing important stuff.'


'Still doing important stuff.'
'Delay the printing of this string, please.'

In web development, this means we can write code to wait for an event to trigger all while a
user goes on interacting with our app. One such example could be if a user goes to a shopping
site and gets notified that an item is up for sale and only for a limited time. Our asynchronous
code could allow the user to interact with our site and when the sale timer expires, our code
will remove the sale item.

setInterval()
setInterval(() => {
alert('Are you paying attention???')
}, 300000)

The setInterval() would call the alert() function and show a pop-up message of 'Are you
paying attention???' every 300000 milliseconds (or 5 minutes).

While we wait for our alert to chime in every 5 minutes, our users could still use our app!

With setInterval(), we can programmatically create an alarm, a countdown timer, set the
frequency of an animation, and so much more!

const shopForBeans = () => {


return new Promise((resolve, reject) => {
const beanTypes = ['kidney', 'fava', 'pinto', 'black', 'garbanzo'];
setTimeout(()=>{
let randomIndex = Math.floor(Math.random() * 4);
let beanType = beanTypes[randomIndex];
console.log(`2. I bought ${beanType} beans because they were on
sale.`);
resolve(beanType);
}, 1000);
});
}
async function getBeans() {
console.log(`1. Heading to the store to buy beans...`);
let value = await shopForBeans();
console.log(`3. Great! I'm making ${value} beans for dinner tonight!
`);
}
getBeans();

----------------------------------------------------//--------------------------------------------------------

PROMISES

An asynchronous operation is one that allows the computer to “move


on” to other tasks while waiting for the asynchronous operation to
complete.
Cleaning our house, for example, involves asynchronous
operations such as a dishwasher washing our dishes or a
washing machine washing our clothes. While we wait on the
completion of those operations, we’re free to do other chores.

What is a Promise?
Promises are objects that represent the eventual outcome of
an asynchronous operation. A Promise object can be in one of three
states:

We refer to a promise as settled if it is no longer pending— it is either


fulfilled or rejected. Let’s think of a dishwasher as having the states of
a promise:

 Pending: The dishwasher is running but has not completed the


washing cycle.
 Fulfilled: The operation has completed successfully and the
promise now has a resolved value. For example, a request’s
promise might resolve with a JSON object as its
value.The dishwasher has completed the washing cycle and is
full of clean dishes.
 Rejected: This reason is usually an Error of some kind.The
dishwasher encountered a problem (it didn’t receive soap!) and
returns unclean dishes.

If our dishwashing promise is fulfilled, we’ll be able to perform related


tasks, such as unloading the clean dishes from the dishwasher. If it’s
rejected, we can take alternate steps, such as running it again with
soap or washing the dishes by hand.

Constructing a Promise Object


To create a new Promise object, we use the new keyword and
the Promise constructor method:

const executorFunction = (resolve, reject) => { };


const myFirstPromise = new Promise(executorFunction);

The Promise constructor method takes a function parameter called


the executor function which runs automatically when the constructor
is called. The executor function generally starts an asynchronous
operation and dictates how the promise should be settled.

The executor function has two function parameters, usually


referred to as the resolve() and reject() functions.
The resolve() and reject() functions aren’t defined by the
programmer. When the Promise constructor runs, JavaScript will
pass its own resolve() and reject() functions into the executor
function.

 resolveis a function with one argument. Under the hood, if


invoked, resolve() will change the promise’s status
from pending to fulfilled, and the promise’s resolved value
will be set to the argument passed into resolve().
 reject is a function that takes a reason or error as an
argument. Under the hood, if invoked, reject() will change the
promise’s status from pending to rejected, and the promise’s
rejection reason will be set to the argument passed
into reject().

Let’s look at an example executor function in a Promise constructor:

const executorFunction = (resolve, reject) => {


if (someCondition) {
resolve('I resolved!');
} else {
reject('I rejected!');
}
}
const myFirstPromise = new Promise(executorFunction);

EXERCICIO:

const inventory = {
sunglasses: 0,
pants: 1088,
bags: 1344
};
const myExecutor = (resolve, reject) => {
if(inventory.sunglasses > 0) {
resolve('Sunglasses order processed.');
} else {
reject('That item is sold out.');
}
}
function orderSunglasses() {
return new Promise(myExecutor);
}
const orderPromise = orderSunglasses();
console.log(orderPromise);

The Node setTimeout() Function


is a Node API (a comparable API is provided by
setTimeout()
web browsers). setTimeout() has two parameters: a callback
function and a delay in milliseconds.
const delayedHello = () => {
console.log('Hi! This is an asynchronous greeting!');
};
setTimeout(delayedHello, 2000);

Let’s look at how we’ll be using setTimeout() to construct


asynchronous promises:

const returnPromiseFunction = () => {


return new Promise((resolve, reject) => {
setTimeout(( ) => {resolve('I resolved!')}, 1000);
});
};
const prom = returnPromiseFunction();

Consuming Promises
Promise objects come with an aptly named .then() method. It
allows us to say, “I have a promise, when it
settles, then here’s what I want to happen…”

In the case of our dishwasher promise, the dishwasher will run then:

 If our promise rejects, this means we have dirty dishes, and


we’ll add soap and run the dishwasher again.
 If our promise fulfills, this means we have clean dishes, and
we’ll put the dishes away.

.then() is a higher-order function— it takes two callback


functions as arguments. We refer to these callbacks as handlers.
When the promise settles, the appropriate handler will be invoked
with that settled value.

One important feature of .then() is that it always returns a


promise.

Success and Failure Callback Functions

To handle a “successful” promise, or a promise that resolved, we


invoke .then() on the promise, passing in a success handler callback
function:

const prom = new Promise((resolve, reject) => {


resolve('Yay!');
});
const handleSuccess = (resolvedValue) => {
console.log(resolvedValue);
};
prom.then(handleSuccess); // Prints: 'Yay!'

With typical promise consumption, we won’t know whether a promise


will resolve or reject, so we’ll need to provide the logic for either case.
We can pass both a success callback and a failure callback to .then().

let prom = new Promise((resolve, reject) => {


let num = Math.random();
if (num < .5 ){
resolve('Yay!');
} else {
reject('Ohhh noooo!');
}
});
const handleSuccess = (resolvedValue) => {
console.log(resolvedValue);
};
const handleFailure = (rejectionReason) => {
console.log(rejectionReason);
};
prom.then(handleSuccess, handleFailure);

EXERCICIO (Só analisar):

const inventory = {
sunglasses: 1900,
pants: 1088,
bags: 1344
};
const checkInventory = (order) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
let inStock = order.every(item => inventory[item[0]] >= item[1])
;
if (inStock) {
resolve(`Thank you. Your order was successful.`);
} else {
reject(`We're sorry. Your order could not be completed because
some items are sold out.`);
}
}, 1000);
})
};
module.exports = { checkInventory };

const inventory = {
sunglasses: 1900,
pants: 1088,
bags: 1344
};
const checkInventory = (order) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
let inStock = order.every(item => inventory[item[0]] >= item[1])
;
if (inStock) {
resolve(`Thank you. Your order was successful.`);
} else {
reject(`We're sorry. Your order could not be completed because
some items are sold out.`);
}
}, 1000);
})
};
module.exports = { checkInventory };

USING CATCH() WITH PROMISES

The .catch() function takes only one argument, onRejected.


Using .catch() accomplishes the same thing as using
a .then() with only a failure handler.

prom
.then((resolvedValue) => {
console.log(resolvedValue);
})
.catch((rejectionReason) => {
console.log(rejectionReason);
});

Chaining Multiple Promises


We take our dirty clothes and put them in the washing machine. If the
clothes are cleaned, then we’ll want to put them in the dryer. After
the dryer runs, if the clothes are dry, then we can fold them and put
them away.

This process of chaining promises together is


called composition.

firstPromiseFunction()
.then((firstResolveVal) => {
return secondPromiseFunction(firstResolveVal);
})
.then((secondResolveVal) => {
console.log(secondResolveVal);
});

 We invoke a function firstPromiseFunction() which returns a


promise.
 We invoke .then() with an anonymous function as the success
handler.
 Inside the success handler we return a new promise— the
result of invoking a second
function, secondPromiseFunction() with the first promise’s
resolved value.
 We invoke a second .then() to handle the logic for the second
promise settling.
 Inside that .then(), we have a success handler which will log
the second promise’s resolved value to the console.

In order for our chain to work properly, we had to return the


promise secondPromiseFunction(firstResolveVal). This ensured
that the return value of the first .then() was our second promise
rather than the default return of a new promise with the same settled
value as the initial.

Using Promise.all()

accepts an array of promises as its argument and


Promise.all()
returns a single promise. That single promise will settle in one of
two ways:
 If every promise in the argument array resolves, the single
promise returned from Promise.all() will resolve with an
array containing the resolve value from each promise in
the argument array.
 If any promise from the argument array rejects, the single
promise returned from Promise.all() will immediately reject with
the reason that promise rejected. This behavior is sometimes
referred to as failing fast.

let myPromises = Promise.all([returnsPromOne(),


returnsPromTwo(), returnsPromThree()]);

myPromises
.then((arrayOfValues) => {
console.log(arrayOfValues);
})
.catch((rejectionReason) => {
console.log(rejectionReason);
});

----------------------------------------------------//--------------------------------------------------------

ASYNC AWAIT

Introduces a new syntax for using promises and generators. Both of


these were already built in to the language. Despite
this, async...await powerfully improves the readability and
scalability of our code.

The async Keyword

The async keyword is used to write functions that handle


asynchronous actions.

async function myFunc() {


// Function body here
};
myFunc();
We can also create async function expressions:

const myFunc = async () => {

myFunc();

asyncfunctions always return a promise. This means we can


use traditional promise syntax, like .then() and .catch with
our async functions. An async function will return in one of three
ways:

 If there’s nothing returned from the function, it will return a


promise with a resolved value of undefined.
 If there’s a non-promise value returned from the function, it will
return a promise resolved to that value.
 If a promise is returned from the function, it will simply return
that promise

async function fivePromise() {


return 5;
}
fivePromise()
.then(resolvedValue => {
console.log(resolvedValue);
}) // Prints 5

EXERCICIO:

async function withAsync(num) {


if(num === 0) {
return 'zero';
} else {
return 'not zero'
}
}
withAsync(100)
.then((resolveValue) => {
console.log(` withAsync(100) returned a promise which resolved to
: ${resolveValue}.`);
})

The await Operator


The await keyword can only be used inside an async function. await is
an operator: it returns the resolved value of a promise. Since
promises resolve in an indeterminate amount of time, await halts, or
pauses, the execution of our async function until a given
promise is resolved.

In the example below, myPromise() is a function that returns a promise


which will resolve to the string "I am resolved now!".

async function asyncFuncExample(){


let resolvedValue = await myPromise();
console.log(resolvedValue);
}
asyncFuncExample(); // Prints: I am resolved now!

Within our async function, asyncFuncExample(), we use await to halt our


execution until myPromise() is resolved and assign its resolved
value to the variable resolvedValue. Then we log resolvedValue to the
console. We’re able to handle the logic for a promise in a way that
reads like synchronous code.

Writing async Functions


let myPromise = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Yay, I resolved!')
}, 1000);
});
}

Now we’ll write two async functions which invoke myPromise():

async function noAwait() {


let value = myPromise();
console.log(value);
}
async function yesAwait() {
let value = await myPromise();
console.log(value);
}
noAwait(); // Prints: Promise { <pending> }
yesAwait(); // Prints: Yay, I resolved!

EXERCICIO:

const shopForBeans = () => {


return new Promise((resolve, reject) => {
const beanTypes = ['kidney', 'fava', 'pinto', 'black', 'garbanzo'];
setTimeout(()=>{
let randomIndex = Math.floor(Math.random() * beanTypes.length);
let beanType = beanTypes[randomIndex];
console.log(`2. I bought ${beanType} beans because they were on sa
le.`);
resolve(beanType);
}, 1000);
});
}
module.exports = shopForBeans;

const shopForBeans = require('./library.js');

async function getBeans() {


console.log(`1. Heading to the store to buy beans...`);
let value = await shopForBeans();
console.log(`3. Great! I'm making ${value} beans for dinner tonight!
`);
}
getBeans();

Handling Dependent Promises

The true beauty of async...await is when we have a series of


asynchronous actions which depend on one another

function nativePromiseVersion() {
returnsFirstPromise()
.then((firstValue) => {
console.log(firstValue);
return returnsSecondPromise(firstValue);
})
.then((secondValue) => {
console.log(secondValue);
});
}
Here’s how we’d write an async function to accomplish the same thing:

async function asyncAwaitVersion() {


let firstValue = await returnsFirstPromise();
console.log(firstValue);
let secondValue = await
returnsSecondPromise(firstValue);
console.log(secondValue);
}
Let’s break down what’s happening in our asyncAwaitVersion() function:

Though using the async...await syntax can save us some typing, the
length reduction isn’t the main point. Given the two versions of
the function, the async...await version more closely resembles
synchronous code, which helps developers maintain and
debug their code. The async...await syntax also makes it easy to
store and refer to resolved values from promises.

Exercicio:

const {shopForBeans, soakTheBeans, cookTheBeans} = require('./


library.js');

async function makeBeans() {


let type = await shopForBeans()
let isSoft = await soakTheBeans(type);
let dinner = await cookTheBeans(isSoft)
console.log(dinner)
}
makeBeans()

Handling Errors

When .catch() is used with a long promise chain, there is no


indication of where in the chain the error was thrown. This can make
debugging challenging.

With async...await, we use try...catch statements for error


handling. By using this syntax, not only are we able to handle errors
in the same way we do with synchronous code, but we can also
catch both synchronous and asynchronous errors. This makes
for easier debugging!

async function usingTryCatch() {


try {
let resolveValue = await asyncFunction('thing that will fail');
let secondValue = await secondAsyncFunction(resolveValue);
} catch (err) {
// Catches any errors in the try block
console.log(err);
}
}
usingTryCatch();

Remember, since async functions return promises we can still use


native promise’s .catch() with an async function

async function usingPromiseCatch() {


let resolveValue = await asyncFunction('thing that will fail');
}
let rejectedPromise = usingPromiseCatch();
rejectedPromise.catch((rejectValue) => {
console.log(rejectValue);
})

This is sometimes used in the global scope to catch final


errors in complex code.

Handling Independent Promises

But what if our async function contains multiple promises which are
not dependent on the results of one another to execute?

async function waiting() {


const firstValue = await firstAsyncThing();
const secondValue = await secondAsyncThing();
console.log(firstValue, secondValue);
}
async function concurrent() {
const firstPromise = firstAsyncThing();
const secondPromise = secondAsyncThing();
console.log(await firstPromise, await secondPromise);
}

In the waiting() function, we pause our function until the first


promise resolves, then we construct the second promise. Once that
resolves, we print both resolved values to the console.

In our concurrent() function, both promises are constructed without


using await. We then await each of their resolutions to print them to
the console.
With our concurrent() function both promises’ asynchronous
operations can be run simultaneously. If possible, we want to
get started on each asynchronous operation as soon as
possible! Within our async functions we should still take
advantage of concurrency, the ability to perform
asynchronous actions at the same time.

Exercicio:

let {cookBeans, steamBroccoli, cookRice, bakeChicken} = require('./


library.js');
// Write your code below:
async function serveDinner() {
const vegetablePromise = steamBroccoli();
const starchPromise = cookRice();
const proteinPromise = bakeChicken();
const sidePromise = cookBeans();
console.log(`Dinner is served. We're having ${await vegetablePromis
e}, ${await starchPromise}, ${await proteinPromise}, and ${await sideP
romise}.`);
}
serveDinner();

Await Promise.all()

We can pass an array of promises as the argument to Promise.all(),


and it will return a single promise. This promise will resolve
when all of the promises in the argument array have resolved.
This promise’s resolve value will be an array containing the
resolved values of each promise from the argument array.

async function asyncPromAll() {


const resultArray = await Promise.all([asyncTask1(),
asyncTask2(), asyncTask3(), asyncTask4()]);
for (let i = 0; i<resultArray.length; i++){
console.log(resultArray[i]);
}
}

In our above example, we await the resolution of a Promise.all().


This Promise.all() was invoked with an argument array
containing four promises (returned from required-in
functions). Next, we loop through our resultArray, and log each
item to the console.

Promise.all() allows us to take advantage of asynchronicity—


each of the four asynchronous tasks can process
concurrently. Promise.all() also has the benefit of failing fast,
meaning it won’t wait for the rest of the asynchronous actions
to complete once any one has rejected.

As soon as the first promise in the array rejects, the promise


returned from Promise.all() will reject with that reason. As it
was when working with native promises, Promise.all() is a good
choice if multiple asynchronous tasks are all required.

----------------------------------------------------//--------------------------------------------------------

HTTP Requests
Understand the basics of how your web browser communicates with the internet.
The internet is made up of a bunch of resources hosted on different
servers. The term “resource” corresponds to any entity on the web,
including HTML files, stylesheets, images, videos, and scripts. To
access content on the internet, your browser must ask these servers
for the resources it wants, and then display these resources to you.
This protocol of requests and responses enables you view this page in
your browser.

What is HTTP?

HTTP stands for Hypertext Transfer Protocol and is used to


structure requests and responses over the internet. HTTP requires
data to be transferred from one point to another over the
network.

The transfer of resources happens using TCP (Transmission


Control Protocol). In viewing this webpage, TCP manages the
channels between your browser and the server (in this case,
codecademy.com). TCP is used to manage many types of internet
connections in which one computer or device wants to send
something to another.
HTTP & TCP: How it Works
When you type an address such as www.codecademy.com into your
browser, you are commanding it to open a TCP channel to the server
that responds to that URL (Uniform Resource Locator). A URL is like
your home address or phone number because it describes
how to reach you.

In this situation, your computer, which is making the request,


is called the client. The URL you are requesting is the address
that belongs to the server.

Once the TCP connection is established, the client sends a


HTTP GET request to the server to retrieve the webpage it should
display. After the server has sent the response, it closes the TCP
connection. If you open the website in your browser again, or if your
browser automatically requests something from the server, a new
connection is opened which follows the same process described
above.

Let’s explore an example of how GET requests (the most common


type of request) are used to help your computer (the client) access
resources on the web.

Suppose you want to check out the latest course offerings


from http://codecademy.com. After you type the URL into your
browser, your browser will extract the http part and recognize that it
is the name of the network protocol to use. Then, it takes the domain
name from the URL, in this case “codecademy.com”, and asks the
internet Domain Name Server to return an Internet Protocol (IP)
address.
Now the client knows the destination’s IP address. It then opens a
connection to the server at that address, using the http protocol as
specified. It will initiate a GET request to the server which contains
the IP address of the host and optionally a data payload. The GET
request contains the following text:
If the server is able to locate the path requested, the server might
respond with the header:

HTTP/1.1 200 OK
Content-Type: text/html
This header is followed by the content requested, which in this case is
the information needed to render www.codecademy.com.

The first line of the header, HTTP/1.1 200 OK, is confirmation that the
server understands the protocol that the client wants to communicate
with (HTTP/1.1), and an HTTP status code signifying that the resource
was found on the server. The second line, Content-Type:
text/html, shows the type of content that it will be sending to the
client.
If the server is not able to locate the path requested by the client, it
will respond with the header:

HTTP/1.1 404 NOT FOUND


In this case, the server identifies that it understands the HTTP
protocol, but the 404 NOT FOUND status code signifies that the
specific piece of content requested was not found. This might happen
if the content was moved or if you typed in the URL path incorrectly
or if the page was removed.
An Analogy:
Imagine the internet is a town. You are a client and your
address determines where you can be reached. Businesses in
town, such as Codecademy.com, serve requests that are sent to
them. The other houses are filled with other clients like you that are
making requests and expecting responses from these businesses in
town. This town also has a crazy fast mail service, an army of mail
delivery staff that can travel on trains that move at the speed of light.

Suppose you want to read the morning newspaper. In order to


retrieve it, you write down what you need in a language
called HTTP and ask your local mail delivery staff agent to
retrieve it from a specific business. The mail delivery person
agrees and builds a railroad track (connection) between your
house and the business nearly instantly, and rides the train
car labeled “TCP” to the address of the business you
provided.

Upon arriving at the business, she asks the first of several free
employees ready to fulfill the request. The employee searches for the
page of the newspaper that you requested but cannot find it and
communicates that back to the mail delivery person.

The mail delivery person returns on the light speed train, ripping up
the tracks on the way back, and tells you that there was a problem
“404 Not Found.” After you check the spelling of what you had
written, you realize that you misspelled the newspaper title. You
correct it and provide the corrected title to the mail delivery person.

This time the mail delivery person is able to retrieve it from the
business. You can now read your newspaper in peace until you decide
you want to read the next page, at which point, you would make
another request and give it to the mail delivery person.

What is HTTPS?
Since your HTTP request can be read by anyone at certain network
junctures, it might not be a good idea to deliver information such as
your credit card or password using this protocol. Fortunately, many
servers support HTTPS, short for HTTP Secure, which allows
you to encrypt data that you send and receive.

HTTPS is important to use when passing sensitive or personal


information to and from websites. However, it is up to the businesses
maintaining the servers to set it up. In order to support HTTPS, the
business must apply for a certificate from a Certificate Authority.

----------------------------------------------------//--------------------------------------------------------

Introduction to Web APIs


What are APIs?

An Application Programming Interface (API) is a software tool


that makes it easier for developers to interact with another
application to use some of that application’s functionality.

Imagine we needed to twist a screw into a piece of wood. We could


try to take the screw and twist it in with our fingers, but that would be
difficult and inefficient. Twisting one screw would be hard enough —
having to do it multiple times would be near impossible! Instead, we
could make the task much easier by using a tool that someone else
created, in this case, a screwdriver! When used properly, the
screwdriver can be used for one specific type of screw and
can be reused for the same job over and over again!

Relating this analogy back to APIs, we probably don’t want to


have to write up the same code for the same problems over
and over again. If the right API exists to solve our problem,
we could make it easier on ourselves and use the API instead.

Types of APIs
There are two main categories of web APIs, browser APIs and 3rd
party APIs.

Browser APIs are specific to writing code related to browsers


and give developers access to information that the browser
can also access. One example is the geolocation API which
allows the program to know where a user is when accessing
our app. This specific API requires that the user grant permissions to
the browser to access their geolocation information.
Third-party APIs are apps that provide some type of
functionality or information from a third-party, usually a
company. For example, we could use the OpenWeather API to
get in-depth information about the weather in an area,
forecasts, historical weather data, and more!

Requesting Information from a Third-party API


Each API has a specific structure and protocol that we have to follow
in order to gain access to its functionality.

Rules and Requirements


For OpenWeather, we need to sign up for an account and generate a
special token called an API key that grants our account the ability to
make API requests. These API keys are unique to individual accounts
and should be kept secret. So before committing to a third-party
API, check out their specifications.

Making Requests
For example, when using the OpenWeather API, we need to provide
more information to search for weather information — such
information could include: the name of a city, time of day, the type of
forecast, etc. These specifications for making a request can also be
found in the API documentation.

Response Data
After we make a successful API request, the API sends back data.
Many APIs format their data using JavaScript Object
Notation (JSON) which looks like a JavaScript object. Here’s a
quick example of what JSON data might look like:

{
"temperature" : {
"celcius" : 25,
},
"city": "chicago",
}
It’s then up to us how to determine how to consume, or use,
this information in our apps. If we got back that sample JSON
above, we could parse out the temperature information and
display it on our app.

----------------------------------------------------//--------------------------------------------------------
What Is JSON?
As programmers, we need to be able to transfer our populated
data structures from any language we choose to a format that
is recognizable and readable by other languages and
platforms. Fortunately for us, there exists such a data-exchange
format.

What is JSON?
JSON, or JavaScript Object Notation, is a popular, language-
independent, standard format for storing and exchanging
data. JSON has become the de facto standard that facilitates
storing and sending data between all programming
languages.

Common Uses of JSON


JSON is heavily used to facilitate data transfer in web
applications between a client, such as a web browser, and a
server. A typical example where such data transfer occurs is when
you fill out a web form. The form data is converted from HTML
to JavaScript objects to JSON objects and sent to a remote
web server for processing.

When companies make their data public for other applications, like
Spotify sharing its music library or Google sharing its map
data, the information is formatted in JSON. This way, any
application, regardless of language, can collect and parse the data.

JSON Syntax
Since JSON is derived from the JavaScript programming language, its
appearance is similar to that of JavaScript objects.

A sample JSON object is represented as follows:

{
"student": {
"name": "Rumaisa Mahoney",
"age": 30,
"fullTime": true,
"languages": [ "JavaScript", "HTML", "CSS" ],
"GPA": 3.9,
"favoriteSubject": null
}
}
Note the following syntax rules for JSON:
 JSON property names must be in double-quoted (" ") text even
though JavaScript names do not hold by this stringency.

JSON Data Types

"2014-01-01T23:28:56.782Z"
This above format contains parts which resemble a date and time.
However, as a string, it is hard for a programming language to use as
is. Conveniently, every programming language has built-in
JSON facilities to convert this string into a more readable and
usable format, such as:

Wed Jan 01 2014 13:28:56 GMT-1000 (Hawaiian Standard Time)


This covers the basic description of JSON, its popularity, and its
syntax.

Reading a JSON String

In a typical web application, the JSON data that we receive from a


web request comes in the form of a string. At other times, JSON
data is stored in a file that is used for authentication, configuration, or
database storage. These files typically have a .json extension,
and they have to be opened in order to retrieve the JSON
string in it. In either case, we will need to convert the string to a
format that we can use in order to access its parts. Each
programming language has its own mechanism to handle this
conversion. In JavaScript, for example, we have a built-in JSON
class with a method called .parse() that takes a JSON string
as a parameter and returns a JavaScript object.
The following code converts a JSON string object, jsonData, into a
JavaScript object, jsObject, and logs jsObject on the console.

const jsonData = '{ "book": { "name": "JSON Primer", "price": 29.99,


"inStock": true, "rating": null } }';

const jsObject = JSON.parse(jsonData);

console.log(jsObject);

This will print out jsObject as follows:


{
book: { name: 'JSON Primer', price: 29.99, inStock: true, rating:
null }
}
Once we have converted a JSON object to a JavaScript object,
we can access the individual properties inside the JavaScript
object. To access a value inside a JavaScript object based on its
property name, we can either use dot notation, ( .propertyName), or
bracket notation, (['propertyName']).
For instance, to retrieve the book property of jsObject we could do the
following:
// Using the dot notation
const book = jsObject.book;
console.log(book);
console.log(book.name, book.price, book.inStock);

// Using the bracket notation


const book2 = jsObject['book'];
console.log(book2);
console.log(book2["name"], book2["price"], book2["inStock"]);

{ name: 'JSON Primer', price: 29.99, inStock: true, rating: null }


JSON Primer 29.99 true

Writing a JSON String


Before we can send off our data across the web, we need to
convert them to a JSON string. In JavaScript, we would use the
built-in JSON class method, .stringify() to transform our
JavaScript object to a JSON string.
The following code converts a JavaScript object, jsObject, into
a JSON string, jsonData.
const jsObject = { book: 'JSON Primer', price: 29.99, inStock: true,
rating: null };
const jsonData = JSON.stringify(jsObject);
console.log(jsonData);
This will display the following output:

{ "book": "JSON Primer", "price": 29.99, "inStock": true, "rating":


null }

---------------------------------------------------------------//------------------------------------------------

REQUESTS WITH FETCH API

Introduction to Requests with ES6

Have you ever wondered what happens after you click a “Submit”
button on a web page? For instance, if you are submitting
information, where does the information go? How is the
information processed? The answer to the previous questions
revolves around HTTP requests.

There are many types of HTTP requests. The four most commonly
used types of HTTP requests are GET, POST, PUT, and DELETE.
With a GET request, we’re retrieving, or getting, information
from some source (usually a website).

For a POST request, we’re posting information to a source that


will process the information and send it back.

JavaScript uses an event loop to handle asynchronous function calls.


When a program is run, function calls are made and added to a stack.
The functions that make requests that need to wait for
servers to respond then get sent to a separate queue. Once
the stack has cleared, then the functions in the queue are
executed.

Intro to GET Requests using Fetch

The first type of requests we’re going to tackle is GET requests


using fetch().

The fetch() function:

 Creates a request object that contains relevant information that


an API needs.
 Sends that request object to the API endpoint provided.
 Returns a promise that ultimately resolves to a response
object, which contains the status of the promise with
information the API sent back.

First, call the fetch() function and pass it a URL as a string for the first
argument, determining the endpoint of the request.

fetch('https://api-to-call.com/endpoint')

The.then() method is chained at the end of the fetch() function and in


its first argument, the response of the GET request is passed to the
callback arrow function. The .then() method will fire only after the
promise status of fetch() has been resolved.

Inside the callback function, the ok property of the response object


returns a Boolean value. If there are no errors, response.ok will
be true and the code will return response.json().

If response.ok is a falsy value, our code will throw an error.


throw new Error('Request failed!');

Making a GET Request

The Datamuse API is a word-finding query engine for developers. It


can be used in apps to find words that match a given set of
constraints that are likely in a given context.

If the request is successful, we’ll get back an array of words


that sound like the word we typed into the input field.

We may get some errors as we complete each step. This is because


sometimes we’ve split a single step into one or more steps to make it
easier to follow. By the end, we should be getting no errors.

You might also like