콜백지옥을 구원하기 위한 자바스크립트의 비동기 담당 객체 : promise
<비동기 작업이 가질 수 있는 3가지 상태>
-> 비동기 작업은 한 번 작업이 성공하거나 실패하면 그걸로 끝
Pending -> Fulfilled : resolve(해결)
Pending -> Rejected : reject(거부)
2초 뒤에 전달받은 값이 양수인지 음수인지 판단하는 비동기 작업👇
function isPositive(number,resolve,reject){
setTimeout(()=>{
if(typeof number === "number"){
//성공 -> resolve
resolve(number >= 0 ? "양수" : "음수");
}else{
//실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다");
}
},2000);
}
isPositive(
10,
(res) => {
console.log("성공적으로 수행됨 : ",res);
},
(err) => {
console.log("실패 하였음 : ",err);
}
);
// 성공적으로 수행됨 : 양수
function isPositive(number,resolve,reject){
setTimeout(()=>{
if(typeof number === "number"){
//성공 -> resolve
resolve(number >= 0 ? "양수" : "음수");
}else{
//실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다");
}
},2000);
}
isPositive(
[],
(res) => {
console.log("성공적으로 수행됨 : ",res);
},
(err) => {
console.log("실패 하였음 : ",err);
}
);
// 실패 하였음 : 주어진 값이 숫자형 값이 아닙니다
promise를 이용해서 비동기처리를 다시 한번 만들어보자
function isPositiveP(number){
const executor = (resolve,reject) => { //실행자(비동기 작업을 실질적으로 수행하는 함수)
setTimeout(()=>{
if(typeof number === "number"){
//성공 -> resolve
console.log(number);
resolve(number >= 0 ? "양수" : "음수");
}else{
//실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다");
}
},2000);
};
const asyncTask = new Promise(executor);
return asyncTask;
}
isPositiveP(101);
//101
isPositiveP 함수의 반환값이 Promise로 바뀌어 있음
어떤 함수가 Promise를 반환한다는 것은 이 함수는 비동기 작업을 하고 그 작업의 결과를 Promise 객체로 반환받아서 사용할 수 있는 함수라고 이해하면 됨
function isPositiveP(number){
const executor = (resolve,reject) => { //실행자(비동기 작업을 실질적으로 수행하는 함수)
setTimeout(()=>{
if(typeof number === "number"){
//성공 -> resolve
console.log(number);
resolve(number >= 0 ? "양수" : "음수");
}else{
//실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다");
}
},2000);
};
const asyncTask = new Promise(executor);
return asyncTask;
}
const res = isPositiveP(101);
res
.then((res)=>{ //resolve 수행시 결과값
console.log("작업 성공 : ",res);
})
.catch((err)=>{ //reject 수행시 결과값
console.log("작업 실패 : ",err);
});
//작업 성공 : 양수
function isPositiveP(number){
const executor = (resolve,reject) => { //실행자(비동기 작업을 실질적으로 수행하는 함수)
setTimeout(()=>{
if(typeof number === "number"){
//성공 -> resolve
console.log(number);
resolve(number >= 0 ? "양수" : "음수");
}else{
//실패 -> reject
reject("주어진 값이 숫자형 값이 아닙니다");
}
},2000);
};
const asyncTask = new Promise(executor);
return asyncTask;
}
const res = isPositiveP([]);
res
.then((res)=>{ //resolve 수행시 결과값
console.log("작업 성공 : ",res);
})
.catch((err)=>{ //reject 수행시 결과값
console.log("작업 실패 : ",err);
});
//작업 실패 : 주어진 값이 숫자형 값이 아닙니다
지난번 콜백함수👇
function taskA(a,b,cb){//콜백이라는 의미의 cb
setTimeout(()=>{
const res = a+b; //지역 상수
cb(res);
},3000);
}
function taskB(a,cb){//콜백이라는 의미의 cb
setTimeout(()=>{
const res = a*2; //지역 상수
cb(res);
},1000);
}
function taskC(a,cb){//콜백이라는 의미의 cb
setTimeout(()=>{
const res = a*-1; //지역 상수
cb(res);
},2000);
}
taskA(3,4,(a_res) => { //콜백 지옥
console.log("task A : ",a_res);
taskB(a_res,(b_res) => {
console.log("task B : ",b_res);
taskC(b_res,(c_res) => {
console.log("task C : ",c_res);
});
});
});
// task A : 7
// task B : 14
// task C : -14
콜백지옥을 해결하기 위해 promise를 써보자
function taskA(a,b){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
const res = a+b; //지역 상수
resolve(res);
},3000);
});
}
function taskB(a){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
const res = a*2; //지역 상수
resolve(res);
},1000);
});
}
function taskC(a){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
const res = a*-1; //지역 상수
resolve(res);
},2000);
});
}
taskA(5,1)
.then((a_res) => {
console.log("A RESULT : ",a_res);
return taskB(a_res);
})
.then(b_res)=>{
console.log("B RESULT : ",b_res);
return taskC(b_res);
})
.then(c_res)=>{
console.log("C RESULT : ",c_res);
});
// 이렇게 then 메소드를 계속 이어서 붙이는 것을 then chaining이라고 부름
// A RESULT : 6
// B RESULT : 12
// C RESULT : -12
/*taskA(5,1).then((a_res) => {
console.log("A RESULT : ",a_res);
taskB(a_res).then((b_res)=>{
console.log("B RESULT : ",b_res);
taskC(b_res).then((c_res)=>{
console.log("C RESULT :",c_res);
});
});
});*/ //콜백식
이렇게 promise를 반환하는 함수로 바꾼 이유는 어떤 함수가 promise 객체를 반환한다는 건 그 함수는 비동기적으로 동작하고 반환한 promise 객체를 이용해서 비동기 처리의 결과값을 then과 catch로 이용할 수 있게 만들겠다는 의미
promise 객체를 이용하면 중간에 다른 작업을 넣을 수도 있음
function taskA(a,b){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
const res = a+b; //지역 상수
resolve(res);
},3000);
});
}
function taskB(a){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
const res = a*2; //지역 상수
resolve(res);
},1000);
});
}
function taskC(a){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
const res = a*-1; //지역 상수
resolve(res);
},2000);
});
}
const bPromiseResult = taskA(5,1)
.then((a_res) => {
console.log("A RESULT : ",a_res);
return taskB(a_res);
});
console.log("dhfkjsdnfsdnfkd");
console.log("dhfkjsdnfsdnfkd");
console.log("dhfkjsdnfsdnfkd");
console.log("dhfkjsdnfsdnfkd");
console.log("dhfkjsdnfsdnfkd");
bPromiseResult.then(b_res)=>{
console.log("B RESULT : ",b_res);
return taskC(b_res);
})
.then(c_res)=>{
console.log("C RESULT : ",c_res);
});
// dhfkjsdnfsdnfkd 다섯번
// A RESULT : 6
// B RESULT : 12
// C RESULT : -12
이렇게 promise 객체를 이용하면 이 비동기 처리를 호출하는 코드와 결과를 처리하는 코드를 분리해줄 수 있어서 콜백함수를 피하고 좀 더 가독성 있고, 깔끔한 비동기처리를 할 수 있도록 도와준다.