Skip to content

Oleksandr Starshynov w2 UsingAPIs #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .test-summary/TEST_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## Test Summary

**Mentors**: For more information on how to review homework assignments, please refer to the [Review Guide](https://github.com/HackYourFuture/mentors/blob/main/assignment-support/review-guide.md).

### 3-UsingAPIs - Week2

| Exercise | Passed | Failed | ESLint |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aleksandrstarshynov Great job. To approve this, there are a couple of things we need to update. You can find my comments/ feedbacks for each exercise. Let me know if you have any questions.

|-------------------|--------|--------|--------|
| ex1-programmerFun | 5 | - | ✓ |
| ex2-pokemonApp | 5 | - | ✓ |
| ex3-rollAnAce | 7 | - | ✓ |
| ex4-diceRace | 7 | - | ✓ |
| ex5-vscDebug | - | - | ✓ |
| ex6-browserDebug | - | - | ✓ |
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": true,
"editor.guides.highlightActiveIndentation": true,
"editor.guides.bracketPairsHorizontal": "active"
"editor.guides.bracketPairsHorizontal": "active",
"liveServer.settings.port": 5501
}
56 changes: 24 additions & 32 deletions 3-UsingAPIs/Week2/assignment/ex1-programmerFun/index.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,36 @@
/*------------------------------------------------------------------------------
Full description at: https://github.com/HackYourFuture/Assignments/blob/main/3-UsingAPIs/Week2/README.md#exercise-1-programmer-fun

1. Complete the function `requestData()` using `fetch()` to make a request to
the url passed to it as an argument. The function should return a promise.
Make sure that the promise is rejected in case of HTTP or network errors.
2. Notice that the function `main()` calls `requestData()`, passing it the url
`https://xkcd.now.sh/?comic=latest`. Try and run the code in the browser and
open the browser's console to inspect the data returned from the request.
3. Next, complete the function `renderImage()` to render an image as an `<img>`
element appended to the document's body, using the data returned from the API.
4. Complete the function `renderError()` to render any errors as an `<h1>`
element appended to the document's body.
5. Refactor the `main()` function to use `async/await`.
6. Test error handling, for instance, by temporarily changing the `.sh` in the
url with `.shx`. There is no server at the modified url, therefore this
should result in a network (DNS) error.
------------------------------------------------------------------------------*/
function requestData(url) {
// TODO return a promise using `fetch()`
return fetch(url)
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
});
}

function renderImage(data) {
// TODO render the image to the DOM
console.log(data);
const img = document.createElement('img');
img.src = data.img;
img.alt = data.alt;
img.title = data.title;
img.style.maxWidth = '100%';
document.body.appendChild(img);
}

function renderError(error) {
// TODO render the error to the DOM
console.log(error);
const errorElement = document.createElement('h1');
errorElement.textContent = `Error: ${error.message}`;
errorElement.style.color = 'red';
document.body.appendChild(errorElement);
}

// TODO refactor with async/await and try/catch
function main() {
requestData('https://xkcd.now.sh/?comic=latest')
.then((data) => {
renderImage(data);
})
.catch((error) => {
renderError(error);
});
async function main() {
try {
const data = await requestData('https://xkcd.now.sh/?comic=latest');
renderImage(data);
} catch (error) {
renderError(error);
}
}

window.addEventListener('load', main);
85 changes: 54 additions & 31 deletions 3-UsingAPIs/Week2/assignment/ex2-pokemonApp/index.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,61 @@
/*------------------------------------------------------------------------------
Full description at: https://github.com/HackYourFuture/Assignments/blob/main/3-UsingAPIs/Week2/README.md#exercise-2-gotta-catch-em-all

Complete the four functions provided in the starter `index.js` file:

`fetchData`: In the `fetchData` function, make use of `fetch` and its Promise
syntax in order to get the data from the public API. Errors (HTTP or network
errors) should be logged to the console.

`fetchAndPopulatePokemons`: Use `fetchData()` to load the pokemon data from the
public API and populate the `<select>` element in the DOM.

`fetchImage`: Use `fetchData()` to fetch the selected image and update the
`<img>` element in the DOM.

`main`: The `main` function orchestrates the other functions. The `main`
function should be executed when the window has finished loading.

Use async/await and try/catch to handle promises.

Try and avoid using global variables. As much as possible, try and use function
parameters and return values to pass data back and forth.
------------------------------------------------------------------------------*/
function fetchData(/* TODO parameter(s) go here */) {
// TODO complete this function
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Fetch error:', error);
throw error;
}
}

function fetchAndPopulatePokemons(/* TODO parameter(s) go here */) {
// TODO complete this function
async function fetchAndPopulatePokemons(selectElement) {
const url = 'https://pokeapi.co/api/v2/pokemon?limit=150';
try {
const data = await fetchData(url);
data.results.forEach(pokemon => {
const option = document.createElement('option');
option.value = pokemon.url;
option.textContent = capitalize(pokemon.name);
selectElement.appendChild(option);
});
} catch (error) {
console.error('Error populating Pokémon list:', error);
}
}

function fetchImage(/* TODO parameter(s) go here */) {
// TODO complete this function
async function fetchImage(url, imgElement) {
try {
const data = await fetchData(url);
const imageUrl = data.sprites.front_default;
imgElement.src = imageUrl;
imgElement.alt = data.name;
} catch (error) {
console.error('Error fetching image:', error);
}
}
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}

function main() {
// TODO complete this function
async function main() {
const select = document.createElement('select');
const img = document.createElement('img');
img.alt = 'Select a Pokémon to see its image';
img.style.marginTop = '1rem';

document.body.appendChild(select);
document.body.appendChild(img);

await fetchAndPopulatePokemons(select);

select.addEventListener('change', () => {
const url = select.value;
if (url) {
fetchImage(url, img);
}
});
}
window.addEventListener('load', main);
39 changes: 15 additions & 24 deletions 3-UsingAPIs/Week2/assignment/ex3-rollAnAce.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
/*------------------------------------------------------------------------------
Full description at: https://github.com/HackYourFuture/Assignments/blob/main/3-UsingAPIs/Week2/README.md#exercise-3-roll-an-ace

1. Run the unmodified exercise and observe that it works as advertised. Observe
that the die must be thrown an indeterminate number of times until we get an
ACE or until it rolls off the table.
2. Now, rewrite the body of the `rollDieUntil()` function using async/await and
without using recursion. Hint: a `while` loop may come handy.
3. Refactor the function `main()` to use async/await and try/catch.
------------------------------------------------------------------------------*/
// ! Do not change or remove the next two lines
import { rollDie } from '../../helpers/pokerDiceRoller.js';
/** @import {DieFace} from "../../helpers/pokerDiceRoller.js" */

Expand All @@ -17,24 +6,26 @@ import { rollDie } from '../../helpers/pokerDiceRoller.js';
* @param {DieFace} desiredValue
* @returns {Promise<DieFace>}
*/
export function rollDieUntil(desiredValue) {
// TODO rewrite this function using async/await
return rollDie().then((value) => {
if (value !== desiredValue) {
return rollDieUntil(desiredValue);
export async function rollDieUntil(desiredValue) {
let result;

while (true) {
result = await rollDie();
if (result === desiredValue) {
return result;
}
return value;
});
}
}

// TODO refactor this function to use try/catch
function main() {
rollDieUntil('ACE')
.then((results) => console.log('Resolved!', results))
.catch((error) => console.log('Rejected!', error.message));
async function main() {
try {
const result = await rollDieUntil('ACE');
console.log('Resolved!', result);
} catch (error) {
console.log('Rejected!', error.message);
}
}

// ! Do not change or remove the code below
if (process.env.NODE_ENV !== 'test') {
main();
}
41 changes: 20 additions & 21 deletions 3-UsingAPIs/Week2/assignment/ex4-diceRace.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
/*------------------------------------------------------------------------------
Full description at: https://github.com/HackYourFuture/Assignments/blob/main/3-UsingAPIs/Week2/README.md#exercise-4-dice-race

1. Complete the function `rollDice()` by using `.map()` on the `dice` array
to create an array of promises for use with `Promise.race()`.
2. Refactor the function `main()` using async/await and try/catch.
3. Once you got this working, you may observe that some dice continue rolling
for some undetermined time after the promise returned by `Promise.race()`
resolves. Do you know why? Add your answer as a comment to the bottom of the
file.
------------------------------------------------------------------------------*/
// ! Do not remove these lines
import { rollDie } from '../../helpers/pokerDiceRoller.js';
/** @import {DieFace} from "../../helpers/pokerDiceRoller.js" */

export function rollDice() {
/**
* Rolls five dice and waits for the first one to finish.
* @returns {Promise<DieFace>} The result of the first die roll to finish.
*/
export async function rollDice() {
const dice = [1, 2, 3, 4, 5];
// TODO complete this function; use Promise.race() and rollDie()
rollDie(1); // TODO placeholder: modify as appropriate
const promises = dice.map((dieNumber) => rollDie(dieNumber));
return Promise.race(promises);
}

// Refactor this function to use async/await and try/catch
function main() {
rollDice()
.then((results) => console.log('Resolved!', results))
.catch((error) => console.log('Rejected!', error.message));
async function main() {
try {
const result = await rollDice();
console.log('Resolved!', result);
} catch (error) {
console.log('Rejected!', error.message);
}
}

// ! Do not change or remove the code below
if (process.env.NODE_ENV !== 'test') {
main();
}

// TODO Replace this comment by your explanation that was asked for in the assignment description.

// We are using Promise.race() here in line 11. The logic if it is just to wait for the first promise in the array to resolve.
// No metter either successfully or unsuccessfully. Once the first promise resolves, it "wins" and returns its result.
// However, this does not mean that the rest of the promises in the array will stop.
// No way to stop them as we found in the previous week.
// So, Promise.race() does not cancel other promises, it just does not wait for them to resolve after one of them has already resolved.
11 changes: 7 additions & 4 deletions 3-UsingAPIs/Week2/assignment/ex5-vscDebug.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ async function getData(url) {

function renderLaureate({ knownName, birth, death }) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of things are missing:

console.log(`\nName: ${knownName.en}`);
console.log(`Birth: ${birth.date}, ${birth.place.locationString}`);
console.log(`Death: ${death.date}, ${death.place.locationString}`);
console.log(`Birth: ${birth.date}, ${birth.place.locationString.en}`);
if (death) {
console.log(`Death: ${death.date}, ${death.place.locationString.en}`);
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this exercise to work, we supposed to have additional function renderLaureates that uses forEach method on the laureates array.
The forEach method iterates over each element in the array and applies a callback function to it as follows:

function renderLaureates(laureates) {
  laureates.forEach(renderLaureate);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is working as expected.

function renderLaureates(laureates) {
Expand All @@ -20,12 +22,13 @@ function renderLaureates(laureates) {

async function fetchAndRender() {
try {
const laureates = getData(
const { laureates } = await getData(
'http://api.nobelprize.org/2.0/laureates?birthCountry=Netherlands&format=json&csvLang=en'
);
renderLaureates(laureates);
renderLaureates(laureates);
} catch (err) {
console.error(`Something went wrong: ${err.message}`);
console.log(err.stack);
}
}

Expand Down
22 changes: 14 additions & 8 deletions 3-UsingAPIs/Week2/assignment/ex6-browserDebug/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
/*
Full description at:https://github.com/HackYourFuture/Assignments/blob/main/3-UsingAPIs/Week2/README.md#exercise-6-using-the-browser-debugger
*/

async function getData(url) {
const response = await fetch(url);
return response.json();
Expand Down Expand Up @@ -30,8 +26,12 @@ function renderLaureate(ul, { knownName, birth, death }) {
const li = createAndAppend('li', ul);
const table = createAndAppend('table', li);
addTableRow(table, 'Name', knownName.en);
addTableRow(table, 'Birth', `${birth.date}, ${birth.place.locationString}`);
addTableRow(table, 'Death', `${death.date}, ${death.place.locationString}`);

const birthInfo = birth ? `${birth.date}, ${birth.place.locationString.en}` : 'Unknown';
addTableRow(table, 'Birth', birthInfo);

const deathInfo = death ? `${death.date}, ${death.place.locationString.en}` : 'Unknown';
addTableRow(table, 'Death', deathInfo);
}

function renderLaureates(laureates) {
Expand All @@ -41,10 +41,16 @@ function renderLaureates(laureates) {

async function fetchAndRender() {
try {
const laureates = getData(
const data = await getData(
'https://api.nobelprize.org/2.0/laureates?birthCountry=Netherlands&format=json&csvLang=en'
);
renderLaureates(laureates);
const laureates = data.laureates;

if (laureates) {
renderLaureates(laureates);
} else {
console.error('No laureates data available');
}
} catch (err) {
console.error(`Something went wrong: ${err.message}`);
}
Expand Down
17 changes: 17 additions & 0 deletions 3-UsingAPIs/Week2/test-reports/ex1-programmerFun.report.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
*** Unit Test Error Report ***

PASS .dist/3-UsingAPIs/Week2/unit-tests/ex1-programmerFun.test.js (11.957 s)
api-wk2-ex1-programmerFun
✅ HTML should be syntactically valid (135 ms)
✅ should have all TODO comments removed
✅ should use `fetch()`
✅ should use async/wait (1 ms)
✅ should use try/catch

Test Suites: 1 passed, 1 total
Tests: 5 passed, 5 total
Snapshots: 0 total
Time: 12.465 s
Ran all test suites matching /\/Users\/hackmyfuture\/HYF\/HYF-Assignments-cohort52\/.dist\/3-UsingAPIs\/Week2\/unit-tests\/ex1-programmerFun.test.js/i.
No linting errors detected.
No spelling errors detected.
Loading