728x90
반응형
1. 동기(Synchronous)와 비동기(Asynchronous) 개념
- 동기 : 순차적으로 코드 실행 0
- 비동기 : 순차적으로 코드 실행 X
- 콜백 패턴 -> 실행의 순서를 보장하기 위해 각각의 함수에 콜백을 추가해야 함
const a = (callback) => {
setTimeout(() => {
console.log(1)
// callback 함수 실행
callback()
}, 1000)
}
const b = () => {
setTimeout(() => {
console.log(2)
// callback 함수 실행
}, 1000)
}
const c = () => console.log(3)
// 추가하는 콜백은 점점 안쪽으로 들여쓰기되어 파고 드는 패턴 생성 == 콜백 지옥
a(() => {
b(()=>{
c()
})
})
// 예제2
const getMovies = (movieName, callback) => {
fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
.then(res => res.json())
.then(res => {
console.log(res)
callback()
})
}
// 서버로 요청은 겨울왕국이 먼저지만, 응답 시간은 보장할 수 없음
// 그래서 getMovies()로 따로따로 실행하면 랜덤으로 출력됨
// 콜백지옥으로 변경한 코드 -> promise 클래스로 관리해야함
getMovies('frozen', ()=>{
console.log('겨울왕국!')
getMovies('avengers', ()=> {
console.log('어벤저스!')
getMovies('avatar', ()=> {
console.log('아바타!')
})
})
})
2. Promise
// promise
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)
// then() 안의 콜백은 ( ()=>{} ) a 함수 resolve 매개변수로 들어가서
// 콘솔에 숫자 1출력하고 resolve()로 호출됨
// a()
// .then(b)
// .then(c)
// .then(d)
// .then(() => console.log("done"))
a()
.then(()=>{ b()
})
.then(()=>{ c()
})
.then(()=>{
d()
})
// 예제2 promise 변경
const getMovies = (movieName) => {
return new Promise(resolve => {
fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
.then(res => res.json())
.then(res => {
console.log(res)
resolve()
})
})
}
// 서버로 요청은 겨울왕국이 먼저지만, 응답 시간은 보장할 수 없음
// 그래서 getMovies()로 따로따로 실행하면 랜덤으로 출력됨
// 콜백지옥으로 변경한 코드 -> promise 클래스로 관리해야함
getMovies('frozen')
.then(()=>{
console.log('겨울왕국!')
return getMovies('avengers')
})
.then(()=> {
console.log('어벤저스!')
return getMovies('avatar')
})
.then(()=>{
console.log('아바타!')
})
3. Async / Await
// Async / Await
const a = () => {
return new Promise(resolve => {
setTimeout(() => {
console.log(1)
resolve()
}, 1000);
})
}
const b = () => console.log(2)
// a 함수는 promise 인스턴스를 반환하는 비동기 코드로 만들어진 함수로
// 그 내부에 있는 resolve() 키워드를 호출하는 그 부분까지의 실행을 기다렸다가
// 그 다음줄에서 새로운 코드를 실행할 수가 있고, 그러면 b 함수를 호출하게 됨
// 즉, await 키워드는 그 뒤에 있는 비동기함수의 실행을 기다린다는 의미
// promise 인스턴스가 반환이 되어야만 앞에 붙여서 사용 가능
// await 키워드는 async 키워드 함수 안에 있어야함
// 밑의 코드는 a().then(()=>b()) 와 같음
const wrap = async () => {
await a()
b()
}
// 예제2 async/await로 변경
const getMovies = (movieName) => {
return new Promise(resolve => {
fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
.then(res => res.json())
.then(res => {
console.log(res)
resolve()
})
})
}
// getMovies('frozen')
// .then(()=>{
// console.log('겨울왕국!')
// return getMovies('avengers')
// })
// .then(()=> {
// console.log('어벤저스!')
// return getMovies('avatar')
// })
// .then(()=>{
// console.log('아바타!')
// })
const wrap = async() => {
await getMovies('frozen')
// console.log는 프로미스를 반환하는 메소드가 아니기에 앞에 사용 불가능
console.log('겨울왕국!')
await getMovies('avengers')
console.log('어벤저스!')
await getMovies('avatar')
console.log('아바타!')
}
4. resolve, reject 및 에러 핸들링
const delayAdd = (index, cb, errorcb) => {
return new Promise((resolve, reject)=>{
setTimeout(() => {
if (index>10){
// reject는 정상적이지 않을 경우, 실행
reject(`${index}는 10보다 클 수 없습니다.`)
return
}
// resolve는 정상적일 때 실행
console.log(index) // 4
// resolve가 실행되면 reject는 실행 안됨, 둘 중 하나만 실행됨
resolve(index +1)
}, 1000);
})
}
delayAdd(2)
.then(res => console.log(res))
.catch(err => console.error(err))
- async/await 변경
// async, await 패턴으로 변경
const delayAdd = (index) => {
return new Promise((resolve, reject)=>{
setTimeout(() => {
if (index>10){
// reject는 정상적이지 않을 경우, 실행
reject(`${index}는 10보다 클 수 없습니다.`)
return
}
// resolve는 정상적일 때 실행
console.log(index) // 4
// resolve가 실행되면 reject는 실행 안됨, 둘 중 하나만 실행됨
resolve(index +1)
}, 1000);
})
}
delayAdd(15)
.then(res => console.log(res))
.catch(err => console.error(err))
// resolve, reject 상관없이 finally는 항상 실행
.finally(()=> console.log('done'))
const wrap = async () =>{
try {
const res = await delayAdd(15)
console.log(res)
} catch (err) {
console.error(err)
} finally {
console.log('done!!')
}
}
wrap()
const getMovies = movieName => {
return new Promise((resolve, reject)=>{
fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=${movieName}`)
// 응답된 정보를 첫번째 then 메소드로 받고, 해당 내용을 json 메소드를 통해 분석
.then(res => res.json())
// 위의 결과를 두번째 then 메소드에 json 매개변수로 받아서 사용
.then(json => {
if(json.Response === 'False'){
reject(json.Error)
}
resolve(json)
})
.catch(error=>{
reject(error)
})
})
}
let loading = true
// .then()
getMovies('avengers')
.then(movies => console.log('영화 목록:', movies))
.catch(error => console.log('에러 발생:', error))
.finally(()=>loading = false)
// async await 패턴
// 위의 then 과 같은 코드
const wrap = async ()=>{
try {
const movies = await getMovies('avengers')
console.log('영화 목록:', movies)
} catch (error) {
console.log('에러 발생:', error)
} finally {
loading = false
}
}
wrap()
5. 반복문에서 비동기 처리
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', 'avartar']
// titles.forEach(async title => {
// // getmovies 함수는 콜백이 반복될 때 바로바로 실행되고, 아이템 만큼 반복해서
// // 각각 콜백 내부에서만 await 키워드로 기다리는 것 -> 순서대로 출력 불가능해서 foreach말고, for 사용
// const movies = await getMovies(title)
// console.log(title, movies)
// })
const wrap = async() => {
// 비동기 코드를 매 반복마다 기다렸다가 실행하려면 for 사용!!!
for (const title of titles) {
const movies = await getMovies(title)
console.log(title, movies)
}
}
wrap()
6. fetch()
// fetch(주소, 옵션)
// 네트워크를 통해 리소스의 요청 및 응답을 처리 가능
// promise 인스턴스를 반환 -> then 메소드 사용 가능, await 키워드 사용 가능
console.log(fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=avengers`))
fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=avengers`)
.then(res => {
return res.json()
})
.then(json => console.log(json))
// then 과 같은 코드
const wrap = async() => {
const res = await fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=avengers`)
const json = await res.json()
console.log(json)
}
wrap()
// fetch 옵션
fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=avengers`, {
// 어떤 값을 얻어낼 때
// OBDB는 GET으로 해야함
method: 'GET',
// 요청에 대한 정보
headers: {
'Content-Type':'application/json'
},
// 요청에 대한 응답 정보
body: JSON.stringify({
name: 'test',
age : 20,
email:'as@ga.com'
})
})
.then(res => {
return res.json()
})
.then(json => console.log(json))
// then 과 같은 코드
const wrap = async() => {
const res = await fetch(`https://www.omdbapi.com/?apikey=7035c60c&s=avengers`)
const json = await res.json()
console.log(json)
}
wrap()
728x90
반응형
'JS, TS' 카테고리의 다른 글
[JS] 이벤트 1 (0) | 2024.01.15 |
---|---|
[JS] DOM (1) | 2024.01.14 |
[JS] 모듈 (0) | 2024.01.12 |
[JS] 표준내장객체 3 (정적 메소드, 객체, JSON) (0) | 2024.01.12 |
[JS] 표준내장객체 2 (배열) (0) | 2024.01.12 |