by Kyojin Hwang
// 동기적
console.log(1)
console.log(2)
console.log(3)
// 1
// 2
// 3
// 비동기적
console.log(1)
setTimeout(() => {
console.log(2)
}, 1000)
console.log(3)
// 1
// 3
// 2
// ex) second는 무조건 first 이후 실행되어야한다!
// 콜백 실패
function first1() {
setTimeout(() => {
console.log(1)
}, 1000)
}
function second1() {
console.log(2)
}
first1()
second1()
// 2
// 1
// 콜백 성공
function first2(callback) {
setTimeout(() => {
console.log(1)
callback()
}, 1000)
}
function second2() {
console.log(2)
}
first2(second2)
// 1
// 2
이벤트리스너 사용
let btn = document.getElementById('button') // 요소 선택
// 이벤트 리스너를 추가해준다.
btn.addEventListener('click', () => {
// 콜백 함수
console.log(1)
})
고차함수에 사용
// ex) 배열을 두배씩 곱하여 새로운 배열을 생성하는 콜백함수 만들기
let numbers = [2, 4, 6, 8] // 배열 선언
let double = [] // 빈배열 선언
numbers.forEach((num) => {
double.push(num * 2)
// 콜백 함수로 각 요소들 두배로 곱해서 배열에 추간
})
console.log(double) // [4, 8, 12, 16]
서버와 데이터 주고 받을때
fetch('https://jsonplaceholder.typicode.com/users')
.then((res) => {
// fetch 메소드가 성공하면 콜백 함수로 response 인자를 받는다.
return res.json()
// res 객체의 json 매소드를 호출하여 json 데이터 반환한다.
})
.then((data) => {
// json 메소드가 성공하면 콜백 함수로 data 인자를 받는다.
console.log(data)
})
step1(function (value1) {
step2(function (value2) {
step3(function (value3) {
step4(function (value4) {
step5(function (value5) {
step6(function (value6) {
// Do something with value6
})
})
})
})
})
})
해결방법
상태
주의점
resolve
rejecct
then
catch
finally
예시1
const test = (bool) => {
return new Promise((resolve, reject) => {
if (bool) {
resolve('resolve 보낼게~')
} else {
reject('reject 보낼게~')
}
})
}
test(false)
.then((val) => {
console.log(val)
console.log('resolve 성공이다잉')
})
.catch((err) => {
console.error(err)
console.error('reject 받았네...')
})
.finally(() => {
console.log('난 finally 어떠한 경우에도 마지막에 실행!')
})
예시2
const Example = new Promise((resolve, reject) => {
// 비동기 시작
fetch('https://jsonplaceholder.typicode.com/todos/100')
.then((response) => {
if (!response.ok) {
throw new Error(response.status)
}
// JSON 형태로 변환 후 아래의 then으로 넘겨준다.
return response.json()
})
.then((data) => {
resolve(data) // fetch 요청 성공 데이터
})
.catch((error) => {
reject(`${error.message} 에러가 났어!`) // fetch 요청 실패 데이터
})
})
Example.then((data) => {
// 위에 함수에서의 resolve값
console.log('Resolve 값 : ', data)
}).catch((error) => {
console.log(error) // 에러가 났어! 메시지 출력
})
예시1
const a = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(1)
resolve()
}, 1000)
})
}
const b = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(2)
resolve()
}, 1000)
})
}
const c = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(3)
resolve()
}, 1000)
})
}
const d = () => console.log(4)
a()
.then(() => b())
.then(() => c())
.then(() => d())
예시2
function doSomething() {
return new Promise((resolve, reject) => {
resolve(100)
})
}
doSomething()
.then((value1) => {
const data1 = value1 + 50
// 150
return data1
})
.then((value2) => {
// value 2는 위의 data1 값이된다
const data2 = value2 + 50
// 200
return data2
})
.then((value3) => {
// value3은 위의 data2 값이된다.
const data3 = value3 + 50
// 250
return data3
})
.then((value4) => {
// value4 === data3
console.log(value4) // 250 출력
})
// 순차적으로 위에서부터 아래로 값을 전달해준다.
Promise
기반이다.Promise
보다 코드가 길어질 경우 코드 가독성이 더 좋다.try , catch
를 통한 에러핸들링을 한다.await
은 async
안에서만 사용 할 수 있다.예시
const a = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(1)
resolve()
}, 1000)
})
}
const b = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(2)
resolve()
}, 1000)
})
}
const c = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(3)
resolve()
}, 1000)
})
}
const testAsyncAwait = async () => {
await a()
console.log('첫번째!')
await b()
console.log('두번째!')
await c()
console.log('세번쨰!')
}
testAsyncAwait()
// 함수 한개 및 함수에서 인자를 받아서 처리
const testConsole = (clgNumber) => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(clgNumber)
resolve()
}, 1000)
})
}
const testAsyncAwait = async () => {
await testConsole(1)
console.log('첫번째!')
await testConsole(2)
console.log('두번째!')
await testConsole(3)
console.log('세번쨰!')
}
testAsyncAwait()
const getMovies = (movieName) => {
return new Promise((resolve) => {
fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
.then((res) => res.json())
.then((res) => resolve(res))
})
}
const titles = ['frozen', 'avengers', 'avatar']
// forEach는 배열의 순서대로 출력되지않음
// Promise를 기다리지 않는다 (mdn출처).
titles.forEach(async (title) => {
const movies = await getMovies(title)
console.log(title, movies)
})
// 대안 1 for of
const start = async () => {
for (const title of titles) {
const movies = await getMovies(title)
console.log(movies)
}
}
start()
// 대안 2 Promise all
// 하나라도 실패하면 reject 만 보내준다.
const start2 = async () => {
// 각 제목에 대해 getMovies 함수를 호출하여 Promise 배열을 생성합니다.
const movies = await Promise.all(titles.map(getMovies))
movies.map((data) => {
console.log(data)
})
}
start2()
// 대안 3 Promise allSettled
// 실패해도 resolve 된 값과 reject 값을 전체 다보내준다.
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve(1)
}, 3000)
})
const promise2 = new Promise((resolve) => {
setTimeout(() => {
resolve(2)
}, 2000)
})
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('다 무시하고 에러내버려!'))
}, 2500)
})
const start3 = () => {
Promise.allSettled([promise1, promise2, promise3])
.then((result) => console.log(result.map((el) => el.value ?? '실패값')))
.catch((e) => console.error(e))
}
start3()
대표적인 option
// then 방식
const thenApi = () => {
fetch(`https://api.thecatapi.com/v1/images/search?limit=10`)
.then((res) => {
return res.json()
})
.then((data) => console.log(data))
}
// async / await 방식
const asyncApi = async () => {
const res = await fetch(`https://api.thecatapi.com/v1/images/search?limit=${num}`)
const data = await res.json()
console.log(data)
}