Web/JavaScript

자바스크립트 비동기처리에 대한 promise 사용법

_sparrow 2020. 7. 8. 09:00
반응형

Promise() 사용법

 

위 링크에 들어가서 보면 Promise를 통한 비동기 처리에 대한 사용법이 두 가지가 나온다.

하나는 Promise를 객체에 담아서 사용하는 방법이고

하나는 return Promise를 사용하는 방법이다.

 

처음엔 상세히 공부하지않고 예제대로 Promise를 객체선언하고 사용했었다.

또한  Promise를 리턴해서나오는 값을 사용하기 위한 콜백 함수 then()을 정확하게 명시할 수 있어서였다.

 

처음엔 문제없이 처리했었는데 AJAX요청이 포함된 비동기 처리가 필요할 때 생겼다.

AJAX로 비동기 요청을 하고 처리된 값을 어딘가에 대입해야 하는 상황에서 Async와 Await를 사용하게 됐는데 구체적인 모든 코드가 작성되어있지는 않지만 그 문제의 코드다.

 

const detectLng = (data) => {
    const lng new ((resolve, reject) => {
        const xhr = new XMLHttpRequest();

        xhr.open("POST", "localhost/detectLangs", true);
        xhr.setRequestHeader("Content-Type", "application/json");

        const chat = {content : '안녕'};

        xhr.onload = () => resolve(xhr.responseText);
        xhr.onerror = () => reject(xhr.statusText);

        xhr.send(JSON.stringify(chat));
    });
    lng.then((response) => {
        const data = JSON.parse(response);
		console.log('XHR 응답 data값',data.langCode);
        return data.langCode;
        
    }).catch(error => {
        console.log(`에러발생: ${error}`);
    });
};


console.log('detect() 시작 이전');
const detectLngCode = await detectLng();
console.log('대입된 detectLngCode값',detectLngCode); //undefined가 뜬다.

코드 작동 결과 결괏과이 undefined가 뜬다.

로그를 보면 알 수 있듯이 XHR응답처리에 대한 반환까지 기다려주지 않아서 함수에 대한 반환 값이 변수 detectLngCode에 담기지 않는 걸 볼 수 있다.

 

이것에 대해서 찾아보니 Await는 Promise객체가 반환되어야만 동기적으로 처리가 된다고 한다.

 

위의 코드에서는 Promise객체가 변수에 선언되어서 사용되었기 때문에 Promise객체 반환처리가 필요하다.

 

그래서 맨 하단에 return을 작성해주었는데

const detectLng = (data) => {
    const lng new Promise ((resolve, reject) => {
        :
        :
        :
    });
    lng.then((response) => {
        :
        :
        :
    }).catch(error => {
        :
        :
    });
    
    return lng; <- 나머지코드 동일하고 이부분만 추가해서 반환
};

 

맨 위의 코드와는 다르게 동기적으로 처리되어서 변수값이 제대로 표기된다.

하지만 내가 예상한 것과는 반대로 리턴 값은 {"langCode":"ko"}가 아닌 ko가 필요했다. 

 

 

또 뒤적뒤적거린결과 값이 제대로 안 뜨는 이유를 찾았다. promise.then()

 

위의 링크에서 'then() 메서드는 Promise를 리턴하고 두 개의 콜백 함수를 인수로 받습니다, 이어지는 then 호출들을 손쉽게 연결할 수 있습니다.'라고 작성되어있다.

 

위의 코드에선  Promise객체는  resolve 된 값을 lng에 대입 후 처리를 then()에서 하겠다고 한 것이어서 반환은 lng만 된다. 그래서 이어지는 then에 대한 값은 처리가 안된 것이다.

 

하단처럼 lng에 이어서 바로 then을 작성했는데 resolve 된 값을 then으로  lng변수 반환 전에 콜백으로 처리하겠다.라고 하면 되겠다. 

 

const detectLng = (data) => {
    const lng new Promise ((resolve, reject) => {
        :
        :
        :
    }).then((response) => { <- 나머지코드 동일하고 이부분만 변환 lng.then() => .then() lng에 이어서 사용
        :
        :
        :
    }).catch(error => {
        :
        :
    });
    
    return lng; 
};

결괏값은 원하던 대로 ko가 나온다.

 

return new Promise 사용법

앞서 말했듯이 Await는 Promise객체가 반환이 되어야만 동기적으로 처리한다.

위의 코드에선 함수 하단에 return으로 Promise객체가 담긴 변수를 반환한다는걸 명시했지만 다른 방법이 있다.

 

return new Promise 사용법은 Promise객체 비동기 처리 이후에 자동 반환을 해준다. 

const detectLng = () => {
    return new Promise((resolve, reject) => { <-바뀐부분
        const xhr = new XMLHttpRequest();

        xhr.open("POST", "localhost/detectLangs", true);
        xhr.setRequestHeader("Content-Type", "application/json");

        const chat = {content : '안녕'};

        xhr.onload = () => resolve(xhr.responseText);
        xhr.onerror = () => reject(xhr.statusText);

        xhr.send(JSON.stringify(chat));
    }).then((response) => { 
        console.log('XHR 응답 data값',data.langCode);
        return data.langCode;
        
    }).catch(error => {
        console.log(`에러발생: ${error}`);
    });
};


console.log('detect() 시작 이전');
const detectLngCode = await detectLng();
console.log('대입된 detectLngCode값',detectLngCode);

코드 작동 결과 결괏값이 ko 뜬다

하지만 return new Promise의 단점은 객체가 어느 곳에 담기지 않기 때문에 함수안에 여러개의 Promise객체를 사용해야하는 상황과  promise.all 메소드을 사용할 수 없다.

 

 

# 정리

1. Async&Await에서는 Promise객체가 반환되어야 동기적으로 처리가 된다.

2. Promise객체를 변수 선언해서 사용할지 선언하지 않고 사용할지 구분하자

3. then() 메서드는 처리가 약간 다를 때가 있다.

반응형