SYNCHRONOUS (๋๊ธฐ์ )
๐ ๋๋ถ๋ถ์ ์ฝ๋๋ ๋๊ธฐ์ (Synchronous)์ผ๋ก ์คํ๋ฉ๋๋ค.
๐๋๊ธฐ์ ์ธ ์ฝ๋๋ ํ ์ค์ฉ ์คํ๋ฉ๋๋ค.
๐๊ฐ ์ฝ๋ ๋ผ์ธ์ ์ด์ ๋ผ์ธ์ ์คํ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
๐ ์คํ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ ์ ์ฝ๋ ์คํ์ ์ฐจ๋จํฉ๋๋ค.
ASYNCHRONOUS (๋น๋๊ธฐ์ )
๐ ๋น๋๊ธฐ์ (Asynchronous) ์ฝ๋๋ "๋ฐฑ๊ทธ๋ผ์ด๋"์์ ์คํ๋๋ ์์
์ด ์๋ฃ๋ ํ์ ์คํ๋ฉ๋๋ค.
๐ ๋น๋๊ธฐ์ ์ธ ์ฝ๋๋ ๋
ผ๋ธ๋กํน(Non-blocking)์
๋๋ค.
๐ ์คํ์ ๋น๋๊ธฐ์ ์ธ ์์
์ด ์์
์ ์๋ฃํ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์์ต๋๋ค.
๐ ์ฝ๋ฐฑ ํจ์ ์์ฒด๋ง์ผ๋ก๋ ์ฝ๋๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค.
AJAX
๋น๋๊ธฐ JavaScript์ XML(AJAX)์ ์๊ฒฉ ์น ์๋ฒ์ ๋น๋๊ธฐ์ ์ผ๋ก ํต์ ํ ์ ์๋ ๊ธฐ์ ์ ๋๋ค. AJAX๋ฅผ ์ฌ์ฉํ๋ฉด ์น ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋์ ์ผ๋ก ์์ฒญํ ์ ์์ต๋๋ค.AJAX ํธ์ถ์ ํตํด ์น ์๋ฒ์ HTTP ์์ฒญ์ ๋ณด๋ด๊ณ XML, JSON, HTML๊ณผ ๊ฐ์ ๋ค์ํ ํ์์ผ๋ก ์๋ต์ ๋ฐ์ ์ ์์ต๋๋ค. ์ ์ฒด ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํ์ง ์๊ณ ๋ ์น ํ์ด์ง์ ํน์ ๋ถ๋ถ์ ์ ๋ฐ์ดํธํ ์ ์์ด ์ฌ์ฉ์ ๊ฒฝํ์ ๋ ์ํธ์์ฉ์ ์ด๊ณ ๋ฐ์ํ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค.
๐API(Application Programming Interface): ์ํํธ์จ์ด ์กฐ๊ฐ์ผ๋ก, ๋ค๋ฅธ ์ํํธ์จ์ด๊ฐ ์ฌ์ฉํ ์ ์๋๋ก ์ค๊ณ๋ ๊ฒ์ผ๋ก, ์ ํ๋ฆฌ์ผ์ด์ ๋ค์ด ์๋ก ํต์ ํ ์ ์๊ฒ ํฉ๋๋ค.
๐์น ๊ฐ๋ฐ์์๋ ๋ค์ํ ์ ํ์ API๊ฐ ์์ ์ ์์ต๋๋ค.
DOM API | Geolocation API | Own Class API | "Online" API |
---|
๐"์จ๋ผ์ธ" API: ์๋ฒ์์ ์คํ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก, ๋ฐ์ดํฐ ์์ฒญ์ ๋ฐ๊ณ ์๋ต์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๋ ์ญํ ์ ํฉ๋๋ค.
๐์ฐ๋ฆฌ๋ ์ง์ ์น API๋ฅผ ๊ตฌ์ถํ ์ ์์ต๋๋ค(๋ฐฑ์๋ ๊ฐ๋ฐ์ด ํ์ํ๋ฉฐ, ์๋ฅผ ๋ค์ด node.js๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค) ๋๋ 3rd-party API๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- Weather data
- Data about countries
- Flights data
- Currency conversion data
- APIs for sending email or SMS
- Google Maps
- Millions of possibilities.
const btn = document.querySelector(".btn-country");
const countriesContainer = document.querySelector(".countries");
///////////////////////////////////////
const getCountryData = function (country) {
const request = new XMLHttpRequest();
request.open(`GET`, `https://restcountries.com/v3.1/name/${country}`);
request.send();
console.log(request.responseText);
request.addEventListener(`load`, function () {
const [data] = JSON.parse(this.responseText);
console.log(data);
const lang = Object.values(data.languages);
// languages: {por: 'Portuguese'}
// languages: {kor: 'Korean'} ์์ฑ์ ๊ฐ์ ๊บผ๋ด๊ธฐ์ํจ.
// ์ถ๋ ฅ: Korean, Portuguese
const curr = Object.values(data.currencies)[0].name;
// currencies: KRW: {name: 'South Korean won', symbol: 'โฉ'}
// currencies: EUR: {name: 'Euro', symbol: 'โฌ'} name์ ๊ฐ์ ๊บผ๋ด๊ธฐ์ํจ.
// ์ถ๋ ฅ: South Korean won, Euro
const html = `
<article class="country">
<img class="country__img" src="${data.flags.svg}" />
<div class="country__data">
<h3 class="country__name">${data.name.common}</h3>
<h4 class="country__region">${data.region}</h4>
<p class="country__row"><span>๐ซ</span>${(
+data.population / 1000000
).toFixed(1)}</p>
<p class="country__row"><span>๐ฃ๏ธ</span>${lang}
</p>
<p class="country__row"><span>๐ฐ</span>${curr}</p>
</div>
</article>`;
countriesContainer.insertAdjacentHTML(`beforeend`, html);
countriesContainer.style.opacity = 1;
});
};
getCountryData(`Korea`);
getCountryData(`portugal`);
GET
/rest/v2/alpha/PT HTTP/1.1
---> ์์ ๋ผ์ธ: HTTP ๋ฉ์๋ + ์์ฒญ ๋์ + HTTP ๋ฒ์
Host: www.google.com
User-Agent: Mozilla/5.0
---> HTTP ์์ฒญ ํค๋ (๋ค์ํ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌํฉ๋๋ค)
Accept-Language: en-US
<BODY>
----> ์์ฒญ ๋ณธ๋ฌธ (์๋ฒ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์กํ ๋๋ง ํฌํจ๋๋ฉฐ, ์๋ฅผ ๋ค์ด POST ์์ฒญ ๋ฑ)
HTTP/1.1
200 OK
---> ์์ ๋ผ์ธ: HTTP ๋ฒ์ + ์ํ ์ฝ๋ + ์ํ ๋ฉ์์ง
Date: Fri, 18 Jan 2021
Content-Type: text/html
----> HTTP ์๋ต ํค๋ (๋ค์ํ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌํฉ๋๋ค)
Transfer-Encoding: chunked
<BODY>
----> ์๋ต ๋ณธ๋ฌธ (๋๋ถ๋ถ์ ์๋ต์ ํฌํจ๋ฉ๋๋ค)
const renderCountry = function (data, className = ``) {
const lang = Object.values(data.languages);
const curr = Object.values(data.currencies)[0].name;
const html = `
<article class="country ${className}">
<img class="country__img" src="${data.flags.svg}" />
<div class="country__data">
<h3 class="country__name">${data.name.common}</h3>
<h4 class="country__region">${data.region}</h4>
<p class="country__row"><span>๐ซ</span>${(
+data.population / 1000000
).toFixed(1)}</p>
<p class="country__row"><span>๐ฃ๏ธ</span>${lang}
</p>
<p class="country__row"><span>๐ฐ</span>${curr}</p>
</div>
</article>`;
countriesContainer.insertAdjacentHTML(`beforeend`, html);
countriesContainer.style.opacity = 1;
};
const getCountryAndNeighbour = function (country) {
// AJAX call country 1
const request = new XMLHttpRequest();
request.open(`GET`, `https://restcountries.com/v3.1/name/${country}`);
request.send();
console.log(request.responseText);
request.addEventListener(`load`, function () {
const [data] = JSON.parse(this.responseText);
console.log(data);
// Render Country 1
renderCountry(data);
// Get neighbour country (2)
const neighbour = data.borders?.[0];
if (!neighbour) return;
// AJAX call country 2
const request2 = new XMLHttpRequest();
request2.open(`GET`, `https://restcountries.com/v3.1/alpha/${neighbour}`);
request2.send();
request2.addEventListener(`load`, function () {
const [data2] = JSON.parse(this.responseText);
console.log(data2);
renderCountry(data2, `neighbour`);
});
});
};
getCountryAndNeighbour(`Korea`);
// getCountryAndNeighbour(`portugal`);
/// Callback Hell (โBad Code)
setTimeout(() => {
console.log(`1 second passed`); // 1์ดํ ์ถ๋ ฅ
setTimeout(() => {
console.log(`2 second passed`); // 2์ดํ ์ถ๋ ฅ
setTimeout(() => {
console.log(`3 second passed`); // 3์ดํ ์ถ๋ ฅ
}, 1000);
}, 1000);
}, 1000);
๐ Promise: ๋น๋๊ธฐ ์์ ์ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ด๋ ๊ฐ์ฒด์ ๋๋ค.
๐ ์ข ๋ ๊ฐ๊ฒฐํ๊ฒ
๐ Promise: ๋น๋๊ธฐ์ ์ผ๋ก ์ ๋ฌ๋ ๊ฐ์ ๋ด๋ ์ปจํ ์ด๋์ ๋๋ค.
๐ ์ข ๋ ๊ฐ๊ฒฐํ๊ฒ
๐ Promise: ๋ฏธ๋์ ๊ฐ์ ๋ด๋ ์ปจํ ์ด๋์ ๋๋ค.
๐ ์ด์ ์ฐ๋ฆฌ๋ ๋น๋๊ธฐ ํจ์์ ์ ๋ฌ๋ ์ด๋ฒคํธ์ ์ฝ๋ฐฑ์ ์์กดํ ํ์๊ฐ ์์ต๋๋ค.
๐ ์ฝ๋ฐฑ์ ์ค์ฒฉํ๋ ๋์ , ์ฐ๋ฆฌ๋ ์ฐ์์ ์ธ ๋น๋๊ธฐ ์์
์ ์ํด ํ๋ก๋ฏธ์ค๋ฅผ ์ฒด์ธ์ผ๋ก ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฝ๋ฐฑ ์ง์ฅ์์ ๋ฒ์ด๋ ์ ์์ต๋๋ค
// traditional
const getCountryData = function (country) {
const request = new XMLHttpRequest();
request.open(`GET`, `https://restcountries.com/v3.1/name/${country}`);
request.send();
console.log(request.responseText);
request.addEventListener(`load`, function () {
const [data] = JSON.parse(this.responseText);
console.log(data);
////////////////////////////////////////// Promise๋ฅผ ํตํ ์ฝ๋ ๊ฐ๊ฒฐํ
/// Promise
// const getCountryData = function (country) {
// fetch(`https://restcountries.com/v3.1/name/${country}`)
// .then(function (response) {
// console.log(response);
// return response.json();
// })
// .then(function (data) {
// console.log(data);
// renderCountry(data[0]);
// });
// };
// getCountryData(`south korea`);
/// Promise (arrow function)
const getCountryData = function (country) {
fetch(`https://restcountries.com/v3.1/name/${country}`)
.then((response) => response.json())
.then((data) => renderCountry(data[0]));
};
getCountryData(`south korea`);
const getCountryData = function (country) {
// Country 1
fetch(`https://restcountries.com/v3.1/name/${country}`)
.then((response) => response.json())
.then((data) => {
renderCountry(data[0]);
const neighbour = data[0].borders?.[0];
if (!neighbour) return;
// Country 2
return fetch(`https://restcountries.com/v3.1/alpha/${neighbour}`);
})
.then((response) => response.json())
.then(([data]) => renderCountry(data, `neighbour`));
};
getCountryData(`south korea`);
Promise ์ฒด์ธ์์ ๋ง์ง๋ง์ผ๋ก ํญ์ ์คํ๋์ด์ผ ํ๋ ์ฝ๋๋ฅผ ์ ์ํ๋ ๋ฐ ์ฌ์ฉ, finally ๋ฉ์๋๋ ์ฑ๊ณต ๋๋ ์คํจ ์ฌ๋ถ์ ๊ด๊ณ์์ด ํญ์ ํธ์ถ
Promise๋ ๋น๋๊ธฐ ์์ ์ ์๋ฃ ๋๋ ์คํจ๋ฅผ ๋ํ๋ด๋ ๊ฐ์ฒด, catch ๋ฉ์๋๋ Promise ์ฒด์ธ์์ ์ด์ Promise์์ ๋ฐ์ํ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ์ฌ์ฉ
const getCountryData = function (country) {
// Country 1
fetch(`https://restcountries.com/v3.1/name/${country}`)
.then((response) => response.json())
.then((data) => {
renderCountry(data[0]);
const neighbour = data[0].borders?.[0];
if (!neighbour) return;
// Country 2
return fetch(`https://restcountries.com/v3.1/alpha/${neighbour}`);
})
.then((response) => response.json())
.then(([data]) => renderCountry(data, `neighbour`))
.catch((err) => {
console.error(`${err}๐ฅ๐ฅ๐ฅ`);
renderError(`Something went wrong ๐ฅ๐ฅ ${err.message}. Try again!`);
})
.finally(() => {
countriesContainer.style.opacity = 1;
});
};
btn.addEventListener(`click`, function () {
getCountryData(`south korea`);
});
๋คํธ์ํฌ๊ฐ ์ฐ๊ฒฐ์ด ์๋ ๋๋ฅผ ๊ฐ์ ํ์ฌ ํ ์คํธํ์๋ค.
throw
JavaScript์์ ์์ธ๋ฅผ ๋ฐ์์ํค๋ ๋ฐ ์ฌ์ฉ๋๋ ๊ตฌ๋ฌธ.
์์ธ๋ ์ฝ๋ ์คํ ์ค์ ๋ฐ์ํ๋ ์ค๋ฅ๋ ์๊ธฐ์น ์์ ์ํฉ.
throw ๋ฌธ์ ์ฌ์ฉํ์ฌ ์์ธ๋ฅผ ๋ฐ์์ํค๋ฉด ์์ธ๋ฅผ ์ฒ๋ฆฌํ๋ ์ฝ๋ ๋ธ๋ก์ผ๋ก ์ด๋.
const getJSON = function (url, errorMsg = `Something went wrong`) {
return fetch(url).then((response) => {
if (!response.ok) throw new Error(`${errorMsg} (${response.status})`);
return response.json();
});
}; // getJSON์ด๋ผ๋ ๋ณ์๋ฅผ ๋ง๋ฌ์ผ๋ก์จ ๊ฐํธํ
const getCountryData = function (country) {
// Country 1
getJSON(`https://restcountries.com/v3.1/name/${country}`, `Country not found`)
.then((data) => {
renderCountry(data[0]);
const neighbour = data[0].borders?.[0];
if (!neighbour) throw new Error(`No neighbour found!`);
// Country 2
return getJSON(
`https://restcountries.com/v3.1/alpha/${neighbour}`,
`Country not found`
);
})
.then(([data]) => renderCountry(data, `neighbour`))
.catch((err) => {
console.error(`${err}๐ฅ๐ฅ๐ฅ`);
renderError(`Something went wrong ๐ฅ๐ฅ ${err.message}. Try again!`);
})
.finally(() => {
countriesContainer.style.opacity = 1;
});
};
btn.addEventListener(`click`, function () {
getCountryData(`south korea`);
});
getCountryData(`australia`);
์ด์๋๋ผ๊ฐ ์๋ ๋๋ผ๋ฅผ ์ ํํ๊ฑธ ๊ฐ์ ํ์์๋.
// Coding Challenge #1
// Test data:
// Coordinates 1: 52.508, 13.381 (Latitude, Longitude)
// Coordinates 2: 19.037, 72.873
// Coordinates 3: -33.933, 18.474
// ์ด ๋์ ์์๋ 'whereAmI'๋ผ๋ ํจ์๋ฅผ ์์ฑํ์ฌ GPS ์ขํ์ ๊ธฐ๋ฐํ์ฌ ๊ตญ๊ฐ๋ง์ ๋ ๋๋งํฉ๋๋ค.
// ์ด๋ฅผ ์ํด ์ขํ๋ฅผ ์ง์ค์ฝ๋ฉํ๋ ๋ฐ ๋ ๋ฒ์งธ API๋ฅผ ์ฌ์ฉํ ๊ฒ์
๋๋ค. ๋ฐ๋ผ์ ์ด ๋์ ์์๋ ์ฒ์์ผ๋ก ์ง์ API๋ฅผ ์ฌ์ฉํฉ๋๋ค.
/* 1. 'whereAmI' ํจ์๋ฅผ ์์ฑํฉ๋๋ค. ์ด ํจ์๋ ์๋('lat')์ ๊ฒฝ๋('lng') ๊ฐ์ ์
๋ ฅ์ผ๋ก ๋ฐ์ต๋๋ค. ์ด ๊ฐ๋ค์ GPS ์ขํ์ด๋ฉฐ, ์๋์ ํ
์คํธ ๋ฐ์ดํฐ์ ์์๊ฐ ์์ต๋๋ค. */
/* 2. ์ ๊ณต๋ ์ขํ์ "์ญ ์ง์ค์ฝ๋ฉ"์ ์ํํฉ๋๋ค. ์ญ ์ง์ค์ฝ๋ฉ์ ์ขํ๋ฅผ ์๋ฏธ์๋ ์์น๋ก ๋ณํํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋์์ ๊ตญ๊ฐ ์ด๋ฆ๊ณผ ๊ฐ์ ์ ๋ณด์
๋๋ค.
์ญ ์ง์ค์ฝ๋ฉ์ ์ํํ๊ธฐ ์ํด ๋ค์ API๋ฅผ ์ฌ์ฉํฉ๋๋ค: https://geocode.xyz/api. ์ด URL ํ์์ผ๋ก AJAX ํธ์ถ์ ์ํํฉ๋๋ค: https://geocode.xyz/52.508,13.381?geoit=json.
fetch API์ ํ๋ก๋ฏธ์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค. "getJSON" ํจ์๋ฅผ ์ฌ์ฉํ์ง ์๋๋ก ์ฃผ์ํฉ๋๋ค. ์ด๋ ๋ถ์ ํ์์
๋๋ค.*/
/* 3. ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ ํ, ์ฝ์์์ ํด๋น ์์น์ ๋ํ ๋ชจ๋ ์์ฑ์ ํ์ธํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ดํด๋ด
๋๋ค.
๊ทธ๋ฐ ๋ค์ ์ด ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ ๋ฉ์์ง๋ฅผ ์ฝ์์ ๊ธฐ๋กํฉ๋๋ค: "You are in Berlin, Germany"์ ๊ฐ์ ํ์์ผ๋ก ์ถ๋ ฅํฉ๋๋ค.*/
/* 4. ํ๋ก๋ฏธ์ค ์ฒด์ธ์ ๋์ .catch ๋ฉ์๋๋ฅผ ์ฐ๊ฒฐํ์ฌ ์๋ฌ๋ฅผ ์ฝ์์ ๊ธฐ๋กํฉ๋๋ค. */
/* 5. ์ด API๋ ์ด๋น 3๊ฐ์ ์์ฒญ๋ง ํ์ฉํฉ๋๋ค. ๋น ๋ฅด๊ฒ ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํ๋ฉด ์ฝ๋ 403์ ํจ๊ป ์๋ฌ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
์ด๋ ์์ฒญ์ ๋ํ ์๋ฌ์
๋๋ค. ๊ธฐ์ตํ์ธ์, ์ด ๊ฒฝ์ฐ fetch()๋ ํ๋ก๋ฏธ์ค๋ฅผ ๊ฑฐ๋ถํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ์๋ฏธ ์๋ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ ํ๋ก๋ฏธ์ค๋ฅผ ๊ฑฐ๋ถํ๋ ์๋ฌ๋ฅผ ์์ฑํฉ๋๋ค. */
// Part 2
/* 6. ์ด์ ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๊ตญ๊ฐ๋ฅผ ๋ ๋๋งํ๋ ์๊ฐ์
๋๋ค. ๋ฐ๋ผ์ ์ง์ค์ฝ๋ฉ API ๊ฒฐ๊ณผ์์ ๊ด๋ จ ์์ฑ์ ๊ฐ์ ธ์ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ๊ตญ๊ฐ API์ ์ฐ๊ฒฐํฉ๋๋ค.*/
/* 7. ๋ง์ง๋ง ๊ฐ์์์ ์ํํ ๊ฒ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ตญ๊ฐ๋ฅผ ๋ ๋๋งํ๊ณ ๋ฐ์ํ๋ ๋ชจ๋ ์๋ฌ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. (์ฌ์ง์ด ์ฝ๋๋ฅผ ๋ณต์ฌํด๋ ๋ฉ๋๋ค. ๊ฐ์ ์ฝ๋๋ฅผ ๋ค์ ์
๋ ฅํ ํ์๋ ์์ต๋๋ค) */
const renderCountry = function (data, className = ``) {
const lang = Object.values(data.languages);
const curr = Object.values(data.currencies)[0].name;
const html = `
<article class="country ${className}">
<img class="country__img" src="${data.flags.svg}" />
<div class="country__data">
<h3 class="country__name">${data.name.common}</h3>
<h4 class="country__region">${data.region}</h4>
<p class="country__row"><span>๐ซ</span>${(
+data.population / 1000000
).toFixed(1)}</p>
<p class="country__row"><span>๐ฃ๏ธ</span>${lang}
</p>
<p class="country__row"><span>๐ฐ</span>${curr}</p>
</div>
</article>`;
countriesContainer.insertAdjacentHTML(`beforeend`, html);
countriesContainer.style.opacity = 1;
};
const renderError = function (msg) {
countriesContainer.insertAdjacentText(`beforeend`, msg);
countriesContainer.style.opacity = 1;
};
const getJSON = function (url, errorMsg = `Something went wrong`) {
return fetch(url).then((response) => {
if (!response.ok) throw new Error(`${errorMsg} (${response.status})`);
return response.json();
});
};
const whereAmI = function (lat, lng) {
fetch(
`https://geocode.xyz/${lat},${lng}?geoit=json&auth={my_api}`
)
.then((res) => {
console.log(res);
if (!res.ok) throw new Error(`Problem with geocoding ${res.status}`);
return res.json();
})
.then((data) => {
console.log(data);
console.log(`You are in ${data.city}, ${data.country}`);
return fetch(`https://restcountries.com/v3.1/name/${data.country}`);
})
.then((res) => {
if (!res.ok) throw new Error(`Country not found (${res.status})`);
return res.json();
})
.then(([data]) => renderCountry(data))
.catch((err) => console.error(`${err.message}๐ฅ`));
};
btn.addEventListener(`click`, function () {
whereAmI(52.508, 13.381);
// whereAmI(19.037, 72.873);
whereAmI(-33.933, 18.474);
});
const lotteryPromise = new Promise(function (resolve, rejcet) {
console.log(`Lotter draw is happening ๐ฎ`);
setTimeout(function () {
if (Math.random() >= 0.5) {
resolve(`You WIN ๐ฐ`);
} else {
rejcet(new Error(`You lost your money ๐`));
}
}, 2000);
});
lotteryPromise
.then((res) => console.log(res))
.catch((err) => console.error(err));
// Promisifying setTimeout
const wait = function (seconds) {
return new Promise(function (resolve) {
setTimeout(resolve, seconds * 1000);
});
};
wait(1)
.then(() => {
console.log(`1 second passed`);
return wait(1);
})
.then(() => {
console.log(`2 second passed`);
return wait(1);
})
.then(() => {
console.log(`3 second passed`);
return wait(1);
})
.then(() => console.log(`4 second passed`));
// setTimeout(() => {
// console.log(`1 second passed`);
// setTimeout(() => {
// console.log(`2 second passed`);
// setTimeout(() => {
// console.log(`3 second passed`);
// }, 1000);
// }, 1000);
// }, 1000);
Promise.resolve(`abc`).then((x) => console.log(x));
Promise.reject(new Error(`Problem!`)).catch((x) => console.error(x));
const renderCountry = function (data, className = ``) {
const lang = Object.values(data.languages);
const curr = Object.values(data.currencies)[0].name;
const html = `
<article class="country ${className}">
<img class="country__img" src="${data.flags.svg}" />
<div class="country__data">
<h3 class="country__name">${data.name.common}</h3>
<h4 class="country__region">${data.region}</h4>
<p class="country__row"><span>๐ซ</span>${(
+data.population / 1000000
).toFixed(1)}</p>
<p class="country__row"><span>๐ฃ๏ธ</span>${lang}
</p>
<p class="country__row"><span>๐ฐ</span>${curr}</p>
</div>
</article>`;
countriesContainer.insertAdjacentHTML(`beforeend`, html);
countriesContainer.style.opacity = 1;
};
const renderError = function (msg) {
countriesContainer.insertAdjacentText(`beforeend`, msg);
countriesContainer.style.opacity = 1;
};
const getJSON = function (url, errorMsg = `Something went wrong`) {
return fetch(url).then((response) => {
if (!response.ok) throw new Error(`${errorMsg} (${response.status})`);
return response.json();
});
};
const getPosition = function () {
return new Promise(function (resolve, reject) {
// navigator.geolocation.getCurrentPosition(
// (position) => console.log(position),
// (err) => console.error(err)
navigator.geolocation.getCurrentPosition(resolve, reject);
});
};
getPosition().then((pos) => console.log(pos));
const whereAmI = function () {
getPosition()
.then((pos) => {
const { latitude: lat, longitude: lng } = pos.coords;
return fetch(
`https://geocode.xyz/${lat},${lng}?geoit=json&auth=835312574695071493093x6866`
);
})
.then((res) => {
console.log(res);
if (!res.ok) throw new Error(`Problem with geocoding ${res.status}`);
return res.json();
})
.then((data) => {
console.log(data);
console.log(`You are in ${data.city}, ${data.country}`);
return fetch(`https://restcountries.com/v3.1/name/${data.country}`);
})
.then((res) => {
if (!res.ok) throw new Error(`Country not found (${res.status})`);
return res.json();
})
.then(([data]) => renderCountry(data))
.catch((err) => console.error(`${err.message}๐ฅ`));
};
btn.addEventListener(`click`, whereAmI);
// Coding Challenge #2
/* PART 1
1. 'imgPathโ๋ฅผ ์
๋ ฅ์ผ๋ก ๋ฐ๋ โcreateImageโ ํจ์๋ฅผ ๋ง๋์ธ์.
2. ์ด ํจ์๋ ์๋ก์ด ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ (document.createElement(โimgโ) ์ฌ์ฉ), .src ์์ฑ์ ์ ๊ณต๋ ์ด๋ฏธ์ง ๊ฒฝ๋ก๋ก ์ค์ ํ Promise๋ฅผ ๋ฐํํฉ๋๋ค.
3. ์ด๋ฏธ์ง ๋ก๋ฉ์ด ์๋ฃ๋๋ฉด, โimagesโ ํด๋์ค๋ฅผ ๊ฐ์ง DOM ์์์ ์ถ๊ฐํ๊ณ Promise๋ฅผ resolveํฉ๋๋ค. ์ด๋ fulfilled value๋ ์ด๋ฏธ์ง ์์ ์์ฒด์
๋๋ค. ์ด๋ฏธ์ง ๋ก๋ฉ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ (error ์ด๋ฒคํธ๋ฅผ ๋ฃ๊ธฐ), Promise๋ฅผ rejectํฉ๋๋ค.
PART 2
4. .then์ ์ฌ์ฉํ์ฌ Promise๋ฅผ Consumeํ๊ณ error handler๋ ์ถ๊ฐํ์ธ์.
5. ์ด๋ฏธ์ง๊ฐ ๋ก๋ ๋ ํ, โwaitโ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์คํ์ 2์ด ๋์ ์ผ์ ์ค์งํ์ธ์.
6. 2์ด๊ฐ ์ง๋ ํ, ํ์ฌ ์ด๋ฏธ์ง๋ฅผ ์จ๊ธฐ๊ณ (display CSS ์์ฑ์ 'noneโ์ผ๋ก ์ค์ ), ๋ ๋ฒ์งธ ์ด๋ฏธ์ง๋ฅผ ๋ก๋ํ์ธ์. (ํํธ: โcreateImageโ Promise์์ ๋ฐํ๋ ์ด๋ฏธ์ง ์์๋ฅผ ์ฌ์ฉํ์ฌ ํ์ฌ ์ด๋ฏธ์ง๋ฅผ ์จ๊น๋๋ค. ์ด๋ฅผ ์ํด ์ ์ญ ๋ณ์๊ฐ ํ์ํฉ๋๋ค.)
7. ๋ ๋ฒ์งธ ์ด๋ฏธ์ง๊ฐ ๋ก๋ ๋ ํ, ๋ค์ 2์ด ๋์ ์คํ์ ์ผ์ ์ค์งํ์ธ์.
8. 2์ด๊ฐ ์ง๋ ํ, ํ์ฌ ์ด๋ฏธ์ง๋ฅผ ์จ๊ธฐ์ธ์.
ํ
์คํธ ๋ฐ์ดํฐ: img ํด๋์ ์ด๋ฏธ์ง์
๋๋ค. ์๋ชป๋ ์ด๋ฏธ์ง ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ์ฌ error handler๋ฅผ ํ
์คํธํ์ธ์.
๋คํธ์ํฌ ์๋๋ ๊ฐ๋ฐ ๋๊ตฌ ๋คํธ์ํฌ ํญ์์ "Fast 3G"๋ก ์ค์ ํ์ธ์. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ด๋ฏธ์ง๊ฐ ๋๋ฌด ๋นจ๋ฆฌ ๋ก๋๋ฉ๋๋ค. */
const wait = function (seconds) {
return new Promise(function (resolve) {
setTimeout(resolve, seconds * 1000);
});
};
const imageContainer = document.querySelector(`.images`);
const createImage = function (imgPath) {
return new Promise(function (resolve, reject) {
const img = document.createElement(`img`);
img.src = imgPath;
img.addEventListener(`load`, function () {
imageContainer.append(img);
resolve(img);
});
img.addEventListener(`error`, function () {
reject(new Error(`Image not Found`));
});
});
};
let currentImg;
createImage(`img/img-1.jpg`)
.then((img) => {
currentImg = img;
console.log(`Images 1 loaded`);
return wait(2);
})
.then(() => {
currentImg.style.display = `none`;
return createImage(`img/img-2.jpg`);
})
.then((img) => {
currentImg = img;
console.log(`Images 2 loaded`);
return wait(2);
})
.then(() => {
currentImg.style.display = `none`;
})
.catch((err) => console.error(err));