11.JS 비동기 (asynchronous)
Updated:
callback, Promise
callback 함수란..
- 기존에 동기 방식 (코드가 순서대로 작동하는 방식) - Synchronous code 예시
function a() {
console.log('A')
}
function b() {
console.log('B')
}
b()
a()
// 코드 순서대로 B 가 먼저 출력이 되고 그다음에 A가 출력이 됨
- callback 함수의 개념 : call(호출), back(뒤로, 나중에) 로써 어떤 함수의 로직이 끝난다음에 실행되는 함수를 호출 하는 것이 callback 함수라고 합니다.
// function a 가 1초 뒤에 출력 될 수 있게 설정
function a(callback) { // callback 이라는 매게 변수를 사용해서 A 가 출력된 다음에 B가 출력 될 수 있도록 보장이 됨
const str = 'Hello A'
setTimeout(() => {
console.log('A')
callback(str)
}, 1000)
}
function b() {
console.log('B')
}
a(function (event) { // callback function a 가 실행된 다음에 b가 실행 됨
console.log(event)
b()
})
- 위의 code 처럼 실행순서를 정해서 보장해 나갈 수 있게 됩니다.
// callback 함수 사용 예시
function a(callback) {
setTimeout(() => {
console.log('A')
callback()
}, 1000)
}
function b(callback) {
setTimeout(() => {
console.log('B')
callback()
}, 1000)
}
a(function () {
b(function () {
console.log('Done!')
})
})
그러나!! callback 이 많아 지면 callback 지옥이라는 문제가 발생!!
// callback 지옥 예시
function a(callback) {
setTimeout(() => {
console.log('A')
callback()
}, 1000)
}
function b(callback) {
setTimeout(() => {
console.log('B')
callback()
}, 1000)
}
function c(callback) {
setTimeout(() => {
console.log('C')
callback()
}, 1000)
}
function D(callback) {
setTimeout(() => {
console.log('D')
callback()
}, 1000)
}
a(function () { // callback 이 계속되서 계속 빠져드는거 callback 지옥임
b(function () {
c(function () {
D(function () {
console.log('Done!')
})
})
})
})
-
callback 이 다음 순서를 보장하는 장점을 가지고 있지만, 코드가 많아지면 복잡해져서 사용하기가 어렵습니다.
-
이를 보안하고자 Promise 객체를 사용합니다.
Promise 객체란..
function a() {
// promise 라는 약속의 객체를 반환
return new Promise(function (resolve) {
setTimeout(() => {
console.log('A')
resolve('Hello A')
}, 1000)
})
}
function b() {
console.log('B')
}
async function test() {
const res = await a() // a 의 함수의 호출을 기다린 다음에 b() 가 실행되는 형식 즉, 위의 resolve() 가 호출이 되고 나면 다음 b() 로 넘어간다는 의미 임
console.log('res:', res)
b()
}
test()
- new Promise 를 사용하여 위의 callback 지옥 대신에 비동기로 처리해서 같은 로직 만들기
function a() {
// promise 라는 약속의 객체를 반환
return new Promise(function (resolve) {
setTimeout(() => {
console.log('A')
resolve('Hello A')
}, 1000)
})
}
function b() {
// promise 라는 약속의 객체를 반환
return new Promise(function (resolve) {
setTimeout(() => {
console.log('B')
resolve('Hello B')
}, 1000)
})
}
function c() {
// promise 라는 약속의 객체를 반환
return new Promise(function (resolve) {
setTimeout(() => {
console.log('C')
resolve('Hello C')
}, 1000)
})
}
function d() {
// promise 라는 약속의 객체를 반환
return new Promise(function (resolve) {
setTimeout(() => {
console.log('D')
resolve('Hello D')
}, 1000)
})
}
async function test() {
const h1 = await a()
const h2 = await b()
const h3 =await c()
const h4 =await d()
console.log('Done!')
console.log(h1, h2, h3, h4)
}
test()
- 즉, code 에서 처리시간이 필요한 경우 promise 객체, 비동기를 사용하여 code 를 실행 할 수 있습니다.
예외 처리 (then, catch, finally)
- 비동기 기능으로 async, await 은 ECMAScript 2017(ES8) 부터 나온 기능이고, Promise 의 개념은 ECMAScript 2015 (ES6) 에 나온 것이기 때문에 만약, async, await 을 사용할 수 없는 경우에는 Promise.then(), catch(), finally()을 사용하여 비동기 환경을 설정 할 수 있습니다.
Promise.then()
-
then() 은 다음 실행을 보장해주는 method
-
async, await 이 잘 작동 되지 않은 경우에는 위와 같은 방식으로 then()을 사용하여 비동기 기능을 작동 시킬 수 있습니다.
function a() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('A')
resolve()
}, 1000)
})
}
function b() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('B')
resolve()
}, 1000)
})
}
function c() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('C')
resolve()
}, 1000)
})
}
function d() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('D')
resolve()
}, 1000)
})
}
function test() {
a()
.then(() => b())
.then(() => c())
.then(() => d())
.then(() => {
console.log('Done!')
})
}
test()
Promise.catch()
-
reject 거부 하는것인데 어떠한 조건에 맞을경우 true 일때, reject 를 사용해서 resolve() 가 더 이상 작동하지 못하도록 하는입니다
-
reject 를 callback 에서 불러서 사용하는 것이 .catch() method 입니다
function a(number) {
return new Promise((resolve, reject) => {
if (number > 4) {
reject()
return
}
setTimeout(() => {
console.log('A')
resolve()
}, 1000)
})
}
function test() {
a(7)
.then(() => {
console.log('Resolve!')
})
.catch(() => {
console.log('Reject!')
})
}
test()
Promise.finally()
-
finally() 는 마지막에 무조건 실행되는 callback 을 사용할 때 쓰는 method 입니다.
-
즉, .then() 이 실행된 다음에 .catch() 가 실행 안되도 마지막에는 .finally() 가 작동이 되고, 반대로 .catch() 가 실행된다음에도 .finally()는 시작되는 구조가 됩니다.
function a(number) {
return new Promise((resolve, reject) => {
if (number > 4) {
reject()
return
}
setTimeout(() => {
console.log('A')
resolve()
}, 1000)
})
}
function test() {
a(7)
.then(() => {
console.log('Resolve!')
})
.catch(() => {
console.log('Reject!')
})
.finally(() => {
console.log('Done!')
})
}
test()
async, await 을 사용해서 예외처리 사용하기
-
try {}, catch() {} 를 사용해서 await 구문에 error 가 발생했을 경우 catch 로 넘겨서 처리 할 수 있게 만듭니다.
-
finally {} 도 마찬가지로 try 구문에서 사용할 수 있습니다.
function a(number) {
return new Promise((resolve, reject) => {
if (number > 4) {
reject()
return
}
setTimeout(() => {
console.log('A')
resolve()
}, 1000)
})
}
async function test() {
try {
await a(8)
console.log('Resolve!')
} catch (error) {
console.log('Reject!')
} finally {
console.log('Done!')
}
}
test()
API 비동기 처리 연습
- API 를 불러올때 axios 같은 package 를 통해서 네트워크를 통해 넘어오는 데이터를 기다려야 될때, 비동기를 사용합니다 => 즉!! API 사용시에는 거의 대부분 비동기 처리를 하여, 데이터가 넘어 올때 까지 기다린 다음에 callback 할 수 있게 code 를 작성 합니다.
OMDB API 를 사용하여 비동기 처리
-
Promise 에서 코드의 상태
-
대기(pending): 이행하거나 거부되지 않은 초기 상태.
-
이행(fullfilled): 연산이 성공적으로 완료됨.
-
거부(rejected): 연산이 실패함.
-
// 영화정보를 가져오는 fetchMovies 라는 함수를 따로 만들어서 나중에 코드 재활용 할때도 편하고, data 화 해서 사용할 수 있음
// 추가적인 logic 도 따로 분류해서 처리하기 때문에 용의하게 사용할 수 있음
function fetchMovies(title) {
// pending 상태
const omdbApiKey = '7035c60c123' // 만약 잘못된 api 키가 들어 오면 reject 처리 함
return new Promise(async (resolve, reject) => {
try {
const res = await axios.get(`https://omdbapi.com?apikey=${omdbApiKey}&s=${title}`)
// console.log(res)
// fullfilled 상태
resolve(res)
} catch (error) { // api key 가 틀렸기 때문에 unauthorized error 가 되 401 error 가 됨
console.log(error.messge)
// rejected 상태
reject('Why is not working?')
}
})
}
async function test() {
try {
const res = await fetchMovies('frozen')
console.log(res)
} catch (error) {
console.log(error)
}
}
test()
function jobs() {
fetchMovies('jobs')
.then(res => console.log(res))
.catch(error => { console.log(error)})
}
jobs()
Leave a comment