JS
비동기 프로그램
: 주어진 코드를 순서대로 진행하는 것이 아니라 오래 기다려야하는 작업이 있으면 다음 작업을 먼저 처리하고 나중에 처리하던 작업으로 다시 돌아와서 마무리하는 방식
function add(x, y) {
return x + y;
}
add(1, 2);
→ 파라미터 : x
, y
: 함수에 전달받은 값을 함수 내부로 전달하기 위해 사용하는 변수
→ 아규먼트 : 1
, 2
: 함수에 실제로 전달되는 값
→ 어떤 함수의 아규먼트로 전달되는 함수를 콜백 또는 콜백 함수
❗콜백(Callback) 함수 : 아규먼트로 전달되는 함수
function sayHello(name) {
console.log(`Hello ${name}!`);
}
function sayGoodbye(name) {
console.log(`Goodbye ${name}!`);
}
function printMessage(func, name) {
console.log("Printing message...");
func(name);
}
printMessage((name) => console.log(`Hello ${name}!`), "Bob");
function forEach(array, callback) {
for (let elt of array) {
callback(elt);
}
}
const words = ['JavaScript', 'Java', 'Python'];
// 배열의 요소를 출력하세요. Arrow Function을 사용하세요.
forEach(words, (word) => console.log(word));
function printUpper(word) {
const upper = word.toUpperCase();
console.log(upper);
}
// 배열의 요소를 대문자로 출력하세요. function 키워드로 함수를 선언하고 콜백으로 전달하세요.
forEach(words, printUpper);
console.log("1");
setTimeout(() => console.log("2"), 3000);
console.log("3");
// 1 3 2
→ 오래 걸리는 작업이 있을 때 시간을 절약 → 효율적인 코드
⚡️ 비동기 함수 (Asynchronous Function)
: 함수의 내용을 끝까지 쭉 실행하지 않고 중간에 다른 작업을 처리하다가 다시 돌아와서 마무리를 하는 함수
function sayHello(name) {
console.log(`Hello ${name}!`);
}
console.log('시작');
// setTimeout(sayHello, 2000, 'Codeit');
setTimeout((name) => console.log(`Hello ${name}!`), 2000, 'Codeit');
console.log('끝');
setTimeout()
함수
setTimeout()
이전에 있는 코드 실행setTimeout()
함수 실행: delay
만큼 기다리는 타이머를 시작setTimeout()
이후에 있는 코드 실행delay
가 지나면 callback
실행setInterval()
함수
: 시간 간격을 두고 콜백을 반복적으로 실행
setInterval(callback, interval)
: interval
단위는 밀리초입니다.
setInterval(() => console.log('2초가 지났습니다'), 2000);
DOM의 addEventListener()
함수
const btn = document.querySelector('.my-btn');
btn.addEventListener('click', () => console.log('button clicked!'));
React의 useEffect()
함수
: 콜백을 바로 실행하지 않고 일단 화면을 그리기 때문에 웹 페이지가 더 빨리 로딩되는 것처럼 보이게 할 수 있음
useEffect(() => console.log('render finished!'), []);
Express의 get()
함수
: 리퀘스트가 언제 들어올지를 모르기 때문에 리퀘스트에 대한 처리는 비동기 형태로, 콜백에 파라미터 존재
app.get('/hello', (req, res) => {
res.send('Success!');
});
→ 콜백이 여러번 중첩되는 것
→ 여러 비동기 작업을 연속적으로 처리한다는 문제점
→ 문제를 해결하기 위해 Promise 문법 생성
Promise 객체 ← fetch("api 링크");
콜백 기반
getEmployees((response) => {
json(response, (data) => {
console.log(data);
});
});
Promise 기반
const response = await fetch('...');
const data = await response.json();
console.log(data);
Promise를 다루는 방법
.then()
메소드 + 콜백async
와 await
문법const response = await fetch('...');
const data = await response.json();
console.log(data);
→ Promise
를 리턴하는 표현식이 있다면, 앞에 await
키워드를 사용하여 결과값(파싱된 데이터)을 받아올 수 있다.
→ await
을 사용하면 Promise
가 fulfilled
상태가 될 때까지 기다렸다가 결과값을 돌려준다.
✨ Promise의 3가지 상태
// 여기에 코드를 작성하세요.
const response = await fetch('...');
const data = await response.json();
console.log(data);
→ 제대로 된 비동기 함수로 사용하려면 추가적인 과정 필요
→ await
: async 함수 내에서 or 모듈의 최상위 레벨에서만 사용 가능
main.js
import { printEmployees } from "./asyncFunctions";
printEmployees();
console.log("Task 2");
console.log("Task 3");
// Task 2
// Task 3
// printEmployees 실행결과
asyncFunctions.js
export async function printEmployees() {
const response = await fetch("...");
const data = await response.json();
console.log(data);
}
/*
const printEmployees = async () => {
const response = await fetch("...");
const data = await response.json();
console.log(data);
}
*/
// 여기에 코드를 작성하세요.
export async function printMenus() {
const response = await fetch('...');
const data = await response.json();
console.log(data);
}
async function getEmployees() {
for (let i = 1; i < 11; i++) {
const response = await fetch(`.../${i}`);
const data = await response.json();
console.log(data);
}
}
getEmployees();
async function getEmployee(id) {
const response = await fetch(`.../${id}`);
const data = await response.json();
console.log(data);
}
for (let i = 1; i < 11; i++) {
getEmployee(id);
}
→ 항상 Promise를 리턴한다❗️
const employees = getEmployees(); // Promise
console.log(employees)
import { getMenus } from './asyncFunctions.js';
function getRandomElement(arr) {
const randomIdx = Math.floor(Math.random() * arr.length);
return arr[randomIdx];
}
console.log('메뉴 고르는 중...');
const menus = await getMenus();
const randomMenu = getRandomElement(menus);
console.log(`오늘의 랜덤 메뉴는 ${randomMenu.name}입니다!`);
import { getInterviews, getEmployees } from './asyncFunctions.js';
function addNewEmployee(employees, interview) {
const { name, department } = interview;
const newEmployee = {
id: employees.length + 1,
name,
department,
email: `${name}@codeitmall.kr`,
};
employees.push(newEmployee);
}
const employees = await getEmployees();
const interviews = await getInterviews();
interviews.forEach((interview) => {
if (interview.result === 'pass') {
addNewEmployee(employees, interview);
}
});
console.log(employees);
export async function getEmployees() {
try {
const response = await fetch("...");
const data = await response.json();
console.log(data);
} catch (error) {
console.log("Error!");
return;
} finally {
console.log("Finished");
}
}
→ catch
문 속에서는 에러 처리 가능
→ return
시 함수를 종료
→ finally
는 return
해도 실행하고 함수 종료
export async function getMenus() {
// 여기에 코드를 작성하세요.
try {
const response = await fetch('...');
const menus = await response.json();
return menus;
} catch(error) {
console.log('데이터를 가져오지 못했습니다 :(');
} finally {
console.log('getMenus() 함수가 끝났습니다.');
}
}
→ .then()
메소드 : 앞선 비동기 작업이 완료되면 등록된 콜백을 실행 (Promise 객체의 메소드)
async function getEmployees() {
const response = await fetch("...");
const data = await response.json();
console.log(data);
}
// const dataPromise = fetch("...").then((response) => response.json());
// dataPromise.then((data) => console.log(data));
fetch("...")
.then((response) => response.json())
.then((data) => console.log(data));
fetch("...")
.then((response) => response.json())
.then((data) => console.log(data))
.**catch((error) => console.log("Error!"))
.finally(() => console.log("Finished"));**
→ 위와 같은 역할
→ catch
문 속에서는 에러 처리 가능
→ finally
는 return
해도 실행하고 함수 종료
async function getEmployee(id) {
const response = await fetch(`.../${id}`);
const data = await response.json();
return data;
}
const promises = [];
for (let i = 1; i < 11; i++) {
promises.push(getEmployee(i));
}
const employees = await Promise.all(promises); // try, catch도 가능
console.log(employees);
→ 여러 Promise
를 동시에 기다릴 때 사용
import { getEmployees, getMenus } from './asyncFunctions.js';
const employeesPromise = getEmployees();
const menusPromise = getMenus();
const [employees, menus] = await Promise.all([employeesPromise, menusPromise]);
// 테스트 코드
console.log('직원 데이터:');
console.log(employees);
console.log('메뉴 데이터:');
console.log(menus);