다시 복습~
자바 스크립트는 동기적 언어(synchronous)
동기 방식(sync)
hoisting이 된 이후부터 순차적으로 한줄 한줄 실행
(hoisiting: var, function 선언을 가장 위로 올려주는 것)
한 메서드가 오래걸려도 계속 기다리고 완료되면 다음 메서드 실행 (블로킹)
비동기 방식(async)
안기다리고 먼저 실행(논블로킹)
console.log('1');
setTimeout(function () { //browser API 1초 있다가 콜백함수 실행해
console.log('2');
}, 1000);
console.log('3');
callback
setTimeout(function () { //browser API 1초 있다가 콜백함수 실행해
console.log('2');
}, 1000);
setTimeout에서 전달되는 function 부분 -> 나중에 이 함수를 다시 call 해줘! -> callback
1. 동기적 콜백
function printImmediately(print) {
print();
}
printImmediately(() => console.log('hello'));
2. 비동기적 콜백
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
printWithDelay(() => console.log('async callback'), 2000);
호이스팅까지 된 전체 코드 순서
'use strict';
//호이스팅으로 함수 선언 부분은 가장 위로 올라온다.
//동기적 콜백
function printImmediately(print) {
print();
}
//비동기적 콜백
function printWithDelay(print, timeout) {
setTimeout(print, timeout);
}
//1번 실행 (동기)
console.log('1');
//2번 실행 (1초 기다렸다 출력해) (비동기)
setTimeout(function () { //browser API 1초 있다가 콜백함수 실행해
console.log('2');
}, 1000);
//3번 실행 -2번 안기다리고 출력 (동기)
console.log('3');
//4번 실행 -2번 안기다리고 출력 (동기)
printImmediately(() => console.log('hello'));
//2번 출력 (1초 지남)
//4번 출력 후 2초 있다가 출력 (비동기)
printWithDelay(() => console.log('async callback'), 2000);
콜백 지옥
가독성 지옥
유지보수가 어려움
비지니스 로직을 이해하기 어려움
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if ((id === 'cat' && password === '1234') ||
(id === 'rabbit' && password === '5678')) {
onSuccess(id); //onSuccess 콜백실행
} else {
onError(new Error('not found')); //onError 콜백 실행
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if (user === 'cat') {
onSuccess({ //onSuccess 콜백실행
name: '야옹이',
role: 'admin'
});
} else { //onError 콜백 실행
onError(new Error('no access'));
}
}, 1000);
}
}
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
id,
password,
(user) => { //onSuccess(id)
userStorage.getRoles(
user,
(userWithRole) => {
alert(`Hello! ${userWithRole.name}, you are ${userWithRole.role}`);
},
(error) => {
console.log(error);
});
},
(error) => { //onError
console.log(error)
});
2초 있다 나옴
Promise
콜백 함수 대신에 비동기 프로그래밍을 도와주는 java script에서 제공하는 오브젝트
시간이 오래걸리는 기능들은 Promise를 이용하여 비 동기적으로 처리하는 것이 좋다! (network, read files)
1. state
pending : operation을 수행 중일 때
fulfilled : operation을 성공적으로 완료
rejected : 파일을 찾을 수 없거나 네트워크 오류
2. producer objector
원하는 기능을 수행해서 원하는 데이터를 만들어내는 promise object
콜백함수로 executor를 전달하는데, executor에는 resolve와 reject 콜백 함수가 있다.
//1.producer
const promise = new Promise((resolve, reject) => {
//executor
//=> promise를 만드는 순간 바로 executor가 자동 실행, 네트워크 통신이 일어남
//버튼액션 등엔 어울리지 않음
//resolve 콜백 :정상수행 이후 데이터 전달
//reject 콜백: 문제가 생겼을 때 호출
setTimeout(() => {
resolve('야옹이'); //성공적인 통신을 마치고 가공된 데이터 '야옹이'전달
}, 2000);
});
3. consumer objector
원하는 데이터를 소비하는 promise object
then, catch, finally를 사용
//2. consumers: then, catch, finally
//기능이 정상적으로 수행이 된다면 내가 value값을 가져와서 기능을 수행할거야
promise.then((value) => {
console.log(value); //2초있다 야옹이 출력
})
producer에서 날아온 값이 reject라면
//1.producer
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('no network'));
}, 2000);
});
에러가 잡히지 않는다고 나온다.
error handler 가 필요하므로 consumer에 .catch를 연결해준다
(then이 다시 promise를 반환하기 때문에 chaining으로 쓸 수 있다)
promise
.then((value) => { //resolve 일 때 데이터 다루기
console.log(value); //2초있다 야옹이 출력
})
.catch(error => { //reject 시 에러 핸들링
console.log(error);
});
2초 있다가 작성한 에러 내용이 제대로 나온다.
finally는 성공, 실패 상관없이 무조건 실행된다.
promise
.then((value) => { //resolve 일 때 데이터 다루기
console.log(value); //2초있다 야옹이 출력
})
.catch(error => { //reject 시 에러 핸들링
console.log(error);
})
.finally(() => { // 성공 실패 상관없이 무조건 마지막에 출력
console.log('finally')
});
4. promise 연결
then은 값을 전달할 수도 있고 promise를 전달해도 된다.
const fetchNumber = new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000);
});
fetchNumber
.then(num => num * 2) //2
.then(num => num * 3) //6
.then(num => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num - 1), 1000); //5
});
})
.then(num => console.log(num)); //5
5. error handling
닭->달걀->달걀 후라이를 해주는 promise를 만듦
const getChicken = () => new Promise((resolve, reject) => {
setTimeout(() => resolve('닭'), 1000);
});
const getEgg = (chicken) => new Promise((resolve, reject) => {
setTimeout(() => resolve(`${chicken} => 달걀`), 1000);
})
const cook = (egg) => new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => 달걀 후라이~`), 1000);
});
getChicken()
.then((chicken) => getEgg(chicken))
.then((egg) => cook(egg))
.then(meal => console.log(meal));
//함수 전달시 동일한 값을 그대로 다시 전달할 때 줄여서 쓸수도 있다.
getChicken()
.then(getEgg)
.then(cook)
.then(console.log);
계란 받아오기가 실패한다면?
const getChicken = () => new Promise((resolve, reject) => {
setTimeout(() => resolve('닭'), 1000);
});
const getEgg = (chicken) => new Promise((resolve, reject) => {
setTimeout(() => reject(new Error(`error! ${chicken} => 달걀`)), 1000);
})
const cook = (egg) => new Promise((resolve, reject) => {
setTimeout(() => resolve(`${egg} => 달걀 후라이~`), 1000);
});
getChicken()
.then(getEgg)
.then(cook)
.then(console.log)
.catch(console.log);
이렇게 에러처리를 할 수도 있지만
프로그램(promise chain)에 문제가 되지 않게 오류를 잘 처리할 수 있다.
getChicken()
.then(getEgg)
.catch(error => {
return '오리알!';
})
.then(cook)
.then(console.log)
.catch(console.log);
6. 콜백 지옥 -> promise
먼저 아까 작성한 콜백지옥
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if ((id === 'cat' && password === '1234') ||
(id === 'rabbit' && password === '5678')) {
onSuccess(id); //onSuccess 콜백실행
} else {
onError(new Error('not found')); //onError 콜백 실행
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if (user === 'cat') {
onSuccess({ //onSuccess 콜백실행
name: '야옹이',
role: 'admin'
});
} else { //onError 콜백 실행
onError(new Error('no access'));
}
}, 1000);
}
}
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage.loginUser(
id,
password,
(user) => { //onSuccess(id)
userStorage.getRoles(
user,
(userWithRole) => {
alert(`Hello! ${userWithRole.name}, you are ${userWithRole.role}`);
},
(error) => {
console.log(error);
});
},
(error) => { //onError
console.log(error)
});
promise로 정리한 콜백지옥
class UserStorage {
loginUser(id, password) {
return new Promise((resolve, reject) => {
if ((id === 'cat' && password === '1234') ||
(id === 'rabbit' && password === '5678')) {
resolve(id);
} else {
reject(new Error('not found'));
}
}, 2000);
}
getRoles(user) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (user === 'cat') {
resolve({
name: '야옹이',
role: 'admin'
});
} else {
reject(new Error('no access'));
}
})
}, 1000);
}
}
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage
.loginUser(id, password)
.then(userStorage.getRoles)
.then(user => alert(`Hello! ${user.name}, you are ${user.role}`))
.catch(console.log);
www.youtube.com/watch?v=JB_yU6Oe2eE&list=PLv2d7VI9OotTVOL4QmPfvJWPJvkmv6h-2&index=12
'Web > HTML CSS JS' 카테고리의 다른 글
HTML - 블록 레벨 요소, 인라인 요소, a 태그 관련 (0) | 2020.10.19 |
---|---|
Java Script - 비동기 프로그래밍 2 (async, await, Promise API (all, race)) (0) | 2020.09.28 |
Java Script - JSON (0) | 2020.09.25 |
JavaScript - array api (0) | 2020.09.25 |
Java Script - Array (0) | 2020.09.25 |