본문 바로가기

js

[javascript] 동기와 비동기, 콜백지옥 예제, promise, 에러 핸들링

1. 동기(Synchronous)

  • 정해진 순서대로 코드가 실행됨
  • 서버에 데이터 요청 후 기다려야 함

 

 

2. 비동기(Asynchronous)

  • 언제 코드가 실행될지 예측할 수 없음
  • 서버에 데이터 요청 후 기다리지 않아도 됨(기다리지 않고 다음 코드를 실행)

 

hoisting

var와 function이 선언 위치에 상관없이 맨 위에 선언되는 것

 

 

3. 콜백 지옥 예제

class UserStorage{
    loginUser(id, password, onSuccess, onError){
	setTimeout(() => {
	    if(
	        (id === 'jiwon' && password === 'hi') ||
		(id === 'happy' && password === 'code')
	    ) {
	        onSuccess(id);
    	    } else {
		onError(new Error('ot found'));
	    }
        }, 2000);
    }
    
    getRoles(user, onSuccess, onError){
    	setTimeout(() => {
            if (user === 'jiwon'){
            	onSuccess({name: 'jiwon', role: 'admin'});
            } else{
            	onError(new Error('no access'));
            }
        }, 1000);
    }
    
    
const userStorage = new UserStorage();
const id = prompt('아이디를 입력해 주세요!');
const password = prompt('비밀번호를 입력해 주세요!!');

userStorage.loginUser(
    id,
    password,
    user => {
        userStorage.getRoles(
            user,
            userWithRole => {
                alert(`hello ${userWithRole.name}, you have a ${userWithRole.role} role`)
            },
            error => {
                console.log('에러2')
            }
            );
        },
    error => {console.log('에러1')}
);

 

4. Promise로 콜백 지옥 탈출하기

class UserStorage{
    loginUser(id, password){
    	return new Promise((resolve, reject) => {
	    setTimeout(() => {
	    	if(
	            (id === 'jiwon' && password === 'hi') ||
		    (id === 'happy' && password === 'code')
	    	) {
	            resolve(id);
    	    	} else {
		    reject(error);
	    	}
            }, 2000);
    	});
    }
    
    getRoles(user){
    	return new Promise((resolve, reject) => {
    	    setTimeout(() => {
            	if (user === 'jiwon'){
            	    resolve();
            	} else{
            	    reject();
            	}
            }, 1000);
        })
    };
    
    
const userStorage = new UserStorage();
const id = prompt('아이디를 입력해 주세요!');
const password = prompt('비밀번호를 입력해 주세요!!');
userStorage.loginUser(id, password)
	.then(user => userStorage.getRoles)
    // .then(userStorage.getRoles)
    .then(user => alert(`hello ${user.name}, you have a ${user.role} role`))
    .catch(console.log)

 

5. Promise

  • 자바스크립트 안에 내장된 오브젝트
  • 비동기적 처리를 콜백함수 대신 유용하게 쓸 수 있음
  • State: pending -> fulfilled or rejected
  • Producer, Consumer
  • promise는 전달된 executor라는 함수가 바로 실행됨 (사용자가 원하지 않아도)

 

Producer

const promise = new Promise((resolve, reject) => {
	// 보통 많은 양의 파일을 읽어야 하는 작업일 때 사용함(network)
	console.log('hi');
    // hi
    setTimeout(() => {
    	resolve('jiwon')
        // 성공적으로 이행 했을 때
        reject(new Error('no network'))
        // 이행하지 못 했을 때
    }), 2000;
});

 

Consumers (then, catch, finally)

// 값이 성공적으로 이행된다면
promise.then(value => {
	console.log(value);
});
// jiwon

// 에러가 발생 했을 때 어떻게 처리할 건지
promise.catch(error => {
	console.log(error);
});
// Error: no network

// 성공하든 실패하든 마지막으로 실행하고 싶은 기능이 있을 때 사용
promise.finally(() => {
	console.log('finally');
});
// finally

 

6. Promise chaining

.then 에서는 값을 전달해도 되고 또 다른 promise를 전달해도 됨

const fetchNumber = new Promise((resolve, reject) => {
	stTimeout(() => resolve(1), 1000);
});
// 1초 뒤에 1이 출력

fetchNumber //
	.then(num => num * 2)
	.then(num => num * 3)
	.then(num => {
		return new Promise((resolve, reject) => {
		stTimeout(() => resolve(num - 1), 1000);
		});
	});
	.then(num => console.log(num));
	// 5

 

 

7. Error Handling

const getHen = () =>
	new Promise((resolve, reject) => {
    	setTimeout(() => resolve('닭'), 1000);
	});
    
const getEgg = hen =>
	new Promise((resolve, reject) => {
    	setTimeout(() => resolve('${hen} => 계란'), 1000);
	});
    
const getEgg = egg =>
	new Promise((resolve, reject) => {
    	setTimeout(() => resolve('${egg} => 계란후라이'), 1000);
	});
    
gethen() //
	.then(hen => getEgg(hen));
    .then(egg => getEgg(egg));
    .then(meal => console.log(meal));

// 아래와 같이 생략 가능
gethen() //
	.then(getEgg);
    .then(getEgg);
    .then(console.log);
    
// 결과값 : 닭 => 계란 => 계란후라이

 

에러 발생시

const getHen = () =>
	new Promise((resolve, reject) => {
    	setTimeout(() => resolve('닭'), 1000);
	});
    
const getEgg = hen =>
	new Promise((resolve, reject) => {
    	setTimeout(() => reject(new Error('error!')), 1000);
	});
    
const getEgg = egg =>
	new Promise((resolve, reject) => {
    	setTimeout(() => resolve('${egg} => 계란후라이'), 1000);
	});
    
gethen() //
	.then(getEgg);
    .then(cook);
    .then(console.log);
    .catch(console.log);
	// 결과값 : error!


// 에러 메세지 대신 값을 대체하고 싶을 때
gethen() //
	.then(getEgg);
    .catch(error => {
    	return '빵';
    });
    .then(cook);
    .then(console.log);
    .catch(console.log);
	// 결과값 : 빵 => 계란후라이