A promise is an object that may produce a single value some time in the future
// resolve
function fetch() {
return new Promise(function(resolve, reject) {
// 서버에 데이터를 요청하고 데이터를 받으면 resolve 호출
resolve('fetch result');
};
}
fetch().then(function(data){
console.log(data); // fetch result
});
// reject
function fetchError() {
return new Promise(function(resolve, reject) {
reject('ERROR');
};
}
fetchError().then().catch(function(error){
console.log(error); // ERROR
});
function getData() {
return new Promise(function(resolve, reject) {
$.get('url 주소/products/1', function(response) {
if (response) {
resolve(response);
}
reject(new Error("Request is failed"));
});
});
}
// 위 $.get() 호출 결과에 따라 'response' 또는 'Error' 출력
getData().then(function(data) {
console.log(data); // response 값 출력
}).catch(function(err) {
console.error(err); // Error 출력
});
then()
메서드를 호출하고 나면 새로운 프로미스 객체가 반환되기에 아래와 같이 체이닝이 가능함new Promise(function(resolve, reject){
setTimeout(function() {
resolve(1);
}, 2000);
})
.then(function(result) {
console.log(result); // 1
return result + 10;
})
.then(function(result) {
console.log(result); // 11
return result + 20;
})
.then(function(result) {
console.log(result); // 31
});
async
라는 예약어를 붙이고, 함수 내부 로직 중에 HTTP 통신을 하는 등의 비동기 처리 코드 앞에 await
를 붙임 (비동기 처리 메서드가 꼭 프로미스 객체를 반환해야 await가 의도한대로 동작함에 유의!)function fetchItems() {
return new Promise(function(resolve, reject) {
var items = [1,2,3];
resolve(items)
});
}
async function logItems() {
var resultItems = await fetchItems();
console.log(resultItems); // [1,2,3]
}
@KneeHunter
안녕하세요, 많이 답답하셨을텐데, 우선 늦은 답변에 대하여 사과드립니다.
이제 보니 Promise 에 대한 설명이 많이 부실했었네요. 초심자의 시각으로 생각하지 않고 제가 너무 대충 설명했었던것 같네요
말씀 주신 문제점들 반영하여 해당 강의는 업데이트하도록 하겠습니다.
질문들에 대한 답변입니다..
increaseAndPrint 콜백 지옥의 파라미터에 대한 설명 작동 흐름 설명
초반의 increaseAndPrint 함수에선 첫번째 파라미터 n에 숫자를 받아오고 두번째 파라미터에선 n에 1을 더한 결과값을 인자로 넣어서 호출 할 함수를 받아옵니다. increaseAndPrint가 호출되고나서 또 다시 자기 자신을 호출하기 위해 연달아서 increaseAndPrint가 작성됐습니다.
해당 코드에서는 <increaseAndPrint 호출 -> n 에 1 더함 -> 더한 값을 가지고 다시 increaseAndPrint 호출>이 값이 5가 될때까지 반복됩니다.
resolve 와 reject가 왜 나왔는가
Promise를 만들때에는 resolve와 reject를 파라미터로 받아오는 함수를 인자로 넣어주어야 합니다. async/await 부분에서 질문주셨던건데, reject는 사용하지 않는다면 생략 될 수 있습니다. resolve 는 처리가 성공됐을때 결과 값을 설정해주고 reject는 실패됐을 때 오류를 설정해줍니다.
catch, console.error
Promise 의 catch 함수는 앞서 만든 Promise 에서 reject 한 값을 받아올 때 사용합니다. 여기서 e 는 reject 에 인자로 넣어준 값입니다.
console.error는 console.log 와 달리 빨간색으로 나오게 됩니다. 콘솔에서 에러가 난 것을 더욱 쉽게 알 수 있게 해주죠.
increaseAndPrint 의 파라미터에 콜백이 사라진 이유
콜백을 없앤 이유는 우리가 콜백을 통해서 그 다음 처리 할 작업을 넣어주지 않고 Promise 의 then 을 통해서 하기 위함이었습니다.
error 를 따로 만든 이유
error 에 ValueIsFiveError 라는 이름을 설정해주기 위함이었습니다.
제가 n+1 값이 "반환" 된다고 표현을 했었는데 이 의미가 정확히 'return' 한다는 의미는 아니었고 정확히는 Promise의 결과값으로 n+1을 설정한다는게 더 옳은 표현일 것 같네요. Mozilla 문서에서는 이를 "이행했다" 라는 표현을 사용하기도 합니다.
then
increaseAndPrint(0)의 결과 1을 .then 의 파라미터 n으로 받아와서 다시 increaseAndPrint를 호출합니다.
.then 에서 Promise 를 반환하면 .then 을 다시 연달아서 사용 할 수 있습니다.
Codesandbox 이상한 현상
저장할때마다 코드가 자동으로 다시 실행됩니다. 그런데 그 과정에서 이미 실행된 Promise들이 사라지지 않고 잔존해있어서 저런 현상이 발생했었고 중요한건 아니여서 그냥 넘겼었습니다. 다만, 설명을 하지 않았을때 혼란을 줄 거라 예상을 못했었네요.
node 에서 왜 오류가 나는지
Node 에서 프로미스에서 발생한 에러를 .catch 하지 않으면 "UnhandledPromiseRejectionWarning" 라는 경고 메시지가 뜹니다. 브라우저에서는 "Uncaught (in promise) ValueIsFiveError" 라는 오류가 뜹니다.
catch 왜 했는지
catch를 한 이유는, 에러가 발생했을때 특정 작업을 하기 위함입니다.
catch를 안했을땐 "Uncaught (in promise) ValueIsFiveError" - ValueIsFiveError 가 잡히지 않았다.
했을땐
했을땐 "ValueIsFiveError" 라고 나타납니다.
즉 콘솔에 출려되는 결과가 다릅니다.
함수를 넣어주기
이 부분 설명이 모호하긴 했네요. 제가 그냥이란 말을 저렇게 많이 하는지도 몰랐습니다..ㅎㅎ;
.then 에 인자로 넣어주어야 하는 것은 함수입니다.
.then 에서 새로 함수를 선언하지 않고 increaseAndPrint 를 넣어주면 앞서 호출한 increaseAndPrint 의 결과값을 다시 increaseAndPrint의 인자로 넣어서 호출하게 됩니다.
파라미터를 여러개 받아와야 하는 경우에는 함수를 새로 선언해야 합니다.
thanable객체
/**
* Represents the completion of an asynchronous operation
*/
interface Promise<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
}