JavaScript - Promise, async/await, Generator

dev_jubby·2022년 10월 10일
0

JavaScript

목록 보기
6/6

✨ Promise

resolve는 성공한 경우, reject는 실패했을 때 실행되는 함수이다.
어떤 일이 완료된 이후 실행되는 함수를 콜백함수라고 한다.

const pr = new Promise((resolve, reject) => {
	// code
});

new Promise 생성자가 반환하는 Promise 객체는 state와 result를 프로퍼티로 갖는다.


state는 초기에 pending 상태였다가, resolve가 호출되면 fullfilled가 된다. 이때 result는 resolve 함수로 전달된 값이다.
cosnt pr = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('OK')
  }, 3000)
});

만약 reject가 호출되면 rejected가 된다. 이때의 result는 reject 함수로 전달된 error이다.
cosnt pr = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(new Error('error..'))
  }, 3000)
});

then을 이용해서 resolve와 reject를 처리할 수 있다.

cosnt pr = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('OK')
  }, 3000)
});

pr.then(
  function(result){},
  function(err){}
);

catch는 에러가 발생한 경우 즉 reject인 경우에만 실행된다.
finally는 이행(fullfilled)이든 거부(reject)든 처리가 완료되면 항상 실행된다.

cosnt pr = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('OK')
  }, 3000)
});

pr.then(
	function(result){}
).catch(
	function(err){}
).finally(
  	function(){
      console.log('항상 실행');
    }
)

예제

const pr = new Promise((resolve, reject) => {
  setTimeout(()=> {
    resolve("Ok");
  }, 1000);
});

console.log('시작');
pr.then((result) => {
  console.log(result);
})
.catch((err) => {
  console.log(err);
})
.finally(() => {
  console.log("끝");
});
시작
Ok
끝

const pr = new Promise((resolve, reject) => {
  setTimeout(()=> {
    reject(new Error('err..');
  }, 1000);
});

console.log('시작');
pr.then((result) => {
  console.log(result);
})
.catch((err) => {
  console.log(err);
})
.finally(() => {
  console.log("끝");
});
시작
Error: err..
끝

Promise를 사용하지 않고 callback 함수 사용

/* callback */
const f1 = (callback) => {
  setTimeout(function() {
    console.log('1번 주문 완료');
    callback();
  }, 1000);
});

const f2 = (callback) => {
  setTimeout(function() {
    console.log('2번 주문 완료');
    callback();
  }, 3000);
});

const f3 = (callback) => {
  setTimeout(function() {
    console.log('3번 주문 완료');
    callback();
  }, 2000);
});

console.log('시작');
f1(function(){
	f2(function() {
    	f3(function() {
        	console.log('끝'); // callback hell
        });
    })
})
시작
1번 주문 완료
2번 주문 완료
3번 주문 완료
끝

Promise 사용

/* Promise */
const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() {
      res('1번 주문 완료');
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('2번 주문 완료');
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('3번 주문 완료');
    }, 2000);
  });
};

// 프로미스 페이닝 (Promise chaning)
console.log('시작');
f1()
  .then(res => f2(res))
  .then((res) => f3(res))
  .then((res) => console.log(res));
  .catch(console.log)
  .finally(() => {
    console.log("끝");
  });
시작
1번 주문 완료
2번 주문 완료
3번 주문 완료
끝

reject

/* Promise */
const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() {
      res('1번 주문 완료');
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      rej('xxxx');
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('3번 주문 완료');
    }, 2000);
  });
};

// 프로미스 페이닝 (Promise chaning)
console.log('시작');
f1()
  .then(res => f2(res))
  .then((res) => f3(res))
  .then((res) => console.log(res));
  .catch(console.log)
  .finally(() => {
    console.log("끝");
  });
시작
1번 주문 완료
xxxx
끝

Promise.all()
/* Promise */
const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() {
      res('1번 주문 완료');
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('2번 주문 완료');
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('3번 주문 완료');
    }, 2000);
  });
};

// Promise.all : 시간 절약 가능
Promise.all([f1(), f2(), f3()]);
.then((res) => {
  console.log(res);
});
["1번 주문 완료", "2번 주문 완료", "3번 주문 완료"]

Promise.all() - reject reject가 있을 시 바로 에러가 발생한다.
/* Promise */
const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() {
      res('1번 주문 완료');
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      rej(new Error("xx"));
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('3번 주문 완료');
    }, 2000);
  });
};

// Promise.all
Promise.all([f1(), f2(), f3()]);
.then((res) => {
  console.log(res);
});
Error: xx

Promise.race() Promise.all()은 모든 작업이 완료될 때까지 기다리지만, Promise.race()는 하나라도 1등으로 끝낸다면 끝난다.
/* Promise */
const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() {
      res('1번 주문 완료');
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      rej(new Error("xx"));
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('3번 주문 완료');
    }, 2000);
  });
};

// Promise.race
Promise.race([f1(), f2(), f3()]);
.then((res) => {
  console.log(res);
});
1번 주문 완료



✨ async/await

async

async function getName() {
  return "Jubby";
}
console.log(getName()); // Promise {<fullfilled>: "jubby"}

getName().then(name => {
  console.log(name); // jubby
});
async function getName() {
  return Promise.resolve("jubby");
}
console.log(getName()); // Promise { <pending> }

getName().then(name => {
  console.log(name); // jubby
});
async function getName() {
	throw new Error('Err..');
}

getName().then(name => {
  console.log(name); // Uncaught Error: err..
});

getName().catch(err => {
  console.log(err); // Error: err..
});

await 키워드는 async 함수 내에서만 사용이 가능하다.

/* await */
function getName(name) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(name);
    }, 1000);
  });
}

async function showName() {
  const result = await getName('jubby');
  console.log(result);
}

console.log('시작');
showName(); // 1초 후에 'jubby'가 찍힌다.

Promise를 async/await로 바꾸기

/* async/await */
const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() {
      res('1번 주문 완료');
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('2번 주문 완료');
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('3번 주문 완료');
    }, 2000);
  });
};

console.log("시작");
async function order() {
  const result1 = await f1();
  const result2 = await f2(result1);
  const result3 = await f3(result2);
  console.log(result3);
  console.log("종료");
}
order();
시작
1번 주문 완료
2번 주문 완료
3번 주문 완료
종료

async/await - reject

/* async/await */
const f1 = () => {
  return new Promise((res, rej) => {
    setTimeout(() {
      res('1번 주문 완료');
    }, 1000);
  });
};

const f2 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      rej(new Error('err...');
    }, 3000);
  });
};

const f3 = (message) => {
  console.log(message);
  return new Promise((res, rej) => {
    setTimeout(() {
      res('3번 주문 완료');
    }, 2000);
  });
};

console.log("시작");
async function order() {
  const result1 = await f1();
  const result2 = await f2(result1);
  const result3 = await f3(result2);
  console.log(result3);
  console.log("종료");
}
order();
시작
1번 주문 완료
Uncaught Error: err...

Error catch - try/cathch

console.log("시작");
async function order() {
  try { 
  	const result1 = await f1();
  	const result2 = await f2(result1);
  	const result3 = await f3(result2);
  	console.log(result3);
  } catch (e) {
    console.log(e);
  }
  console.log("종료");
}

order();
시작
1번 주문 완료
Error: err...
종료

async/await - Promise

console.log("시작");
async function order() {
  try { 
  	const result = await Promise.all([f1(), f2(), f3()]);
  	console.log(result);
  } catch (e) {
    console.log(e);
  }
  console.log("종료");
}

order();
시작
["1번 주문 완료", "2번 주문 완료", "3번 주문 완료"]
종료



✨ Generator

함수의 실행을 중간에 멈췄다가 재개할 수 있는 기능
yield 키워드를 사용해서 함수의 실행을 멈출 수 있다.

function* fn() {
  yield 1;
  yield 2;
  yield 3;
  return "finish";
}

const a = fn();

재너레이터 함수를 실행하면 제너레이터 객체가 반환된다.
제너레이터 객체에는 next 메소드가 있다.

function* fn() {
  console.log(1);
  yield 1;
  console.log(2);
  yield 2;
  console.log(3);
  consoel.log(4);
  yield 3;
  return "finish";
}

const a = fn();
a.next(); // 1

next() 메소드를 사용하면, 가장 가까운 yield문을 만날 때까지 실행되고 데이터 객체를 반환한다.

{value: 1, done: false}

반환된 데이터 객체는 value와 done 프로퍼티를 가지는데,
value는 일드 오른쪽에 있는 값이며, 생략하면 undefined
done은 이름 그대로 함수코드가 끝났는지 나타내며, 실행이 끝났으면 true 아니면 false를 반환한다.


제너레이터는 next(), return(), throw() 메서드를 가지고 있다. `a.return('END');` 를 실행하면 그 즉시 done 속성값이 true로 변경.
function* fn() {
  try{
    console.log(1);
    yield 1;
    console.log(2);
    yield 2;
    console.log(3);
    consoel.log(4);
    yield 3;
  	return "finish";
  } catch (e) {
    console.log(e);
  }
}

const a = fn();
a.throw(new Error('err')); // Error catch, done 속성 true.

iterable

  • Symbol.iterator 메서드가 있다.
  • Symbol.iterator는 iterator를 반환해야 한다.

Iterator

  • next 메서드를 가진다.
  • next 메서드는 value와 done 속성을 가진 객체를 반환한다.
  • 작업이 끝나면 done은 true가 된다.
profile
신입 개발자 쥬비의 기술 블로그 입니다.

0개의 댓글