Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

옥수수, 기록

callback, promise 정리 본문

카테고리 없음

callback, promise 정리

ok-soosoo 2022. 11. 23. 23:24

callback

일반 함수 구현 예

function cry() { // cry함수를 실행하면 울고
console.log("cry");
}
 

function sing() { //sing 함수를 실행하면 노래하고
console.log("sing");
}
 

function dance() { // dance 함수를 실행하면 춤추고
console.log("dance");
}

이거를 함수로 활용할 때

1. 기본 함수
기분 좋을때 춤을 추고 싶으면 sing()함수에 dance()로 변경해야함
function checkMood(mood) {
      if (mood === "good") {
             sing();
      } else {
             cry();
      }
}
 
checkMood("good");
checkMood("sad");
콜백 함수 설명에 앞서 일반함수를 살펴보면, checkMood("good");을 실행하면 
sing이 출력됨을 알 수 있다. 하지만, checkMood("good"); 일 때, 
dance가 출력되게 하고싶다면 if조건문에 sing();호출부분을 dance();로 수정해야만 한다.
콜백 함수 사용 (함수를 매개변수로 넣어줌)

위에서 본 checkMood 일반 함수 안에서 호출되는 함수들을 자유롭게 바꾸고싶으면 
콜백 함수를 사용할 수 있다. (자바스크립트에서는 변수로 함수를 넣어서 사용가능한 것을 응용 한 개념이다.)

function checkMoodCallBack(mood, goodCallback, badCallback) {
if (mood === "good") {
goodCallback();
} else {
badCallback();
}
}
 

checkMoodCallBack("good", dance, cry);// 'dance'
checkMoodCallBack("Not bad", dance, sing); // 'sing'

"good"일때 dance를 하도록,  checkMoodCallBack에서 호출할 함수를 지정할 수 있다. 
이렇게 사용할 함수들 마져 선택해서 사용하는 것이 바로 콜백함수이다.

Promise

Promise가 뭘까?

자바스크립트 비동기 처리에 사용되는 객체이다.

** 비동기처리는 특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 JavaScript의 특성을 의미

Promise가 왜 필요하지?

위에 말한 JavaScript의 특성때문에 필요하다. 서버에서 데이터를 받아올 때 시간이 필요한데 다음 코드들은 이것을 기다려주지 않는다. 그래서 이것과 같은 문제를 해결하기 위해 사용하는 것이 Promise이다

Promise의 3가지 상태

밑에도 계속 나오겠지만 프로미스는 상태(states)와 결과(result)를 갖는다.

상태란 Promise의 처리 과정을 의미한다.

  • Pending(대기) : 비동기 처리가 이행되지 않은 상태
// new Promise() 메서드를 호출하면 대기상태가 된다 
new Promise(function(resolve, reject) {
// executor
});
  • Fulfilled(이행) : 비동기 처리가 완료되어 Promise가 결과 값을 반환해준 상태
// promise가 이행되었을 때
new Promise(function(resolve, reject) {
	resolve(1); // result 는 1이 된다
});
  • Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태
// promise가 이행되지 않고 실패, 오류가 발생했을 때
new Promise(function(resolve, reject) {
  reject(-1); // err 는 -1이 된다
});
일반적인 문법

let promise = new Promise(function(resolve, reject) {
  // executor (제작 코드)
});

new Promise에 전달되는 함수는 executor(실행자, 실행 함수)라고 한다.

new Promise가 만들어질 때 executor가 자동으로 만들어지고 실행되는데., 결과를 최종적으로 만들어내는 제작 코드를 포함한다.

인수 resolve와 reject는 JavaScript에서 자체 제공하는 콜백이다. 저 인수는 신경쓰지않고 executor 내부 코드만 잘 신경쓰면 된다.

 

대신 executor에서 결과를 즉시 얻든 늦게 얻든 상관없이 인수로 넘겨준 콜백 중 하나를 반드시 호출해야 한다.

resolve(value) - 일이 성공적으로 끝난 경우 그 결과를 나타내는 value와 함께 호출

reject(error) - 에러 발생 시 에러 객체를 나타내는 error와 함께 호출

 

요약

  1. new Promise 를 사용하면 (resolve, reject)를 인자로 갖는 executor(함수)가 자동으로 생성,실행된다.
  2. 실행이 끝나면 executor는 처리 성공 여부에 따라 resolve나 reject를 호출한다.

setTimeout의 활용

let promise = new Promise(function(resolve, reject) {
  // 프라미스가 만들어지면 executor 함수는 자동으로 실행됩니다.

  // 1초 뒤에 일이 성공적으로 끝났다는 신호가 전달되면서 result는 '완료'가 됩니다.
  setTimeout(() => resolve("완료"), 1000);
});

executor ‘처리’가 시작 된 지 1초 후, resolve(”완료”)가 호출되고 결과가 만들어진다. 이때 promise객체의 상태는 “pending”에서 아래와 같이 변한다.

Promise 객체가 이행될 경우

일이 성공적으로 처리되었을 때의 promise 객체는 ‘fulfilled promise(약속이 이행된 promise)’라고 불린다.

이번에는 executor가 에러와 함께 작업을 거부하는 경우에 대해 살펴보자

let promise = new Promise(function(resolve, reject) {
  // 1초 뒤에 에러와 함께 실행이 종료되었다는 신호를 보냅니다.
  setTimeout(() => reject(new Error("에러 발생!")), 1000);
});

1초 후 reject()가 호출되면 promise의 상태가 “rejected”로 변한다.

Promise 객체가 거절, 오류가 발생한 경우

promise는 성공 또는 실패만 한다.

executor는 resolve와 reject 둘 중 하나를 반드시 호출해야 한다.

let promise = new Promise(function(resolve, reject) {
  resolve("완료");

  reject(new Error("…")); // 무시됨
  setTimeout(() => resolve("…")); // 무시됨
});

resolve와 reject는 인수를 하나만 받고(혹은 아예 받지않고)이미 처리가 끝난 promise의 executor에서 resolve와 reject를 계속 호출하면 무시된다.

** promise를 즉시 이행시킬수도 있다.

let promise = new Promise(function(resolve, reject) {
// 즉시 완료
  resolve("완료"); // 결과("완료")를 즉시 resolve에 전달함
//굳이 setTimeout을 사용하지 않아도 된다!!

});

 

then

.then의 기본문법

promise.then(
  function(result) { /* 결과(result)를 다룹니다 */ },
  function(error) { /* 에러(error)를 다룹니다 */ }
);

.then의 첫 번째 인수는 promise가 이행되었을 때 실행되는 함수 > 여기서 실행 결과를 받는다.

.then의 두 번째 인수는 promise가 거부되었을 때 실행되는 함수 > 여기서 에러를 받는다.

// promise가 이행 O

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("완료!"), 1000); // result = "완료"
});

// resolve 함수는 .then의 첫 번째 함수(인수)를 실행합니다.
promise.then(
  result => alert(result), // 1초 후 "완료!"를 출력
  error => alert(error) // 실행되지 않음
);
------------------------------------------------------------------------------
// promise가 이행 X

let promise = new Promise(function(resolve, reject) { // result = null;
  setTimeout(() => reject(new Error("에러 발생!")), 1000); // error = new Error("에러 발생!"))
});

// reject 함수는 .then의 두 번째 함수를 실행합니다.
promise.then(
  result => alert(result), // 실행되지 않음
  error => alert(error) // 1초 후 "Error: 에러 발생!"을 출력
);

작업이 성공적으로 처리된 경우만 다루고 싶다면 .then에 인수를 하나만 전달하면 된다.

let promise = new Promise(resolve => {
  setTimeout(() => resolve("완료!"), 1000);
});

promise.then(alert); // 1초 뒤 "완료!" 출력

 

catch

에러가 발생한 경우만 다루고 싶다면 .then(null, errorHandlingFunction) 같이 null 을 첫 번째 인수로 전달하면 된다.

.catch(errorHandlingFunction)를 써도 되는데, .catch는 .then에 null을 전달하는 것과 동일하게 작동한다.

let promise = new Promise((resolve, reject) => {
	setTimeout(() => reject(new Error("에러 발생!")), 1000);
});

// .catch(f)는 promise.then(null, f)과 동일하게 작동한다.
promise.catch(alert); //1초 뒤, "Error: 에러 발생!" 출력

문법이 조금 더 간결하다는 점 빼고 .then(null, function)과 동일하다.

// 에러를 처리하는 두가지 방법
function top() {
return new Promise((resolve, reject) {
...
)};

//then의 두번째 인자로 에러처리하는 코드
** top().then(function(success){
…
}, function(err) {   
console.log(err)
});

// catch()로 에러를 처리하는 코드
top().then().catch(function(err) => console.log(err));

// then의 두번째 인자로 에러처리하는 코드보다 catch()를 사용해야 한다. 
// then의 첫번째 콜백함수에서 에러가 나는 경우, 오류를 잡아낼 수 없다.

 

finally

promise가 처리되면(이행 or 거부) f가 항상 실행된다는 점에서 .finally(f) 호출은 .then(f, f)와 유사하다.

new Promise((resolve, reject) => {
  /* 시간이 걸리는 어떤 일을 수행하고, 그 후 resolve, reject를 호출함 */
})
  // 성공·실패 여부와 상관없이 프라미스가 처리되면 실행됨
  .finally(() => 로딩 인디케이터 중지) //.finally에는 인수가 없다
  .then(result => result와 err 보여줌 => error 보여줌)

  1. .finally(() ⇒ ) 에선 promise의 상태와 결과값을 알 수 없다.
  2. finally 핸들러는 자동으로 다음 핸들러에 결과와 에러를 전달한다.
// promise가 이행됐을 때

new Promise((resolve, reject) => {
  setTimeout(() => resolve("결과"), 2000)
})
  .finally(() => alert("프라미스가 준비되었습니다.")) // finally단에서는 result를 알 수 없음
  .then(result => alert(result)); // <-- .then에서 result를 다룰 수 있음

// promise가 거부되었을 때

new Promise((resolve, reject) => {
  throw new Error("에러 발생!");
})
  .finally(() => alert("프라미스가 준비되었습니다.")) // 역시 여기선 result를 모름
  .catch(err => alert(err)); // <-- .catch에서 에러 객체를 다룰 수 있음

// promise의 결과는 finally를 통과해 전달된다.
  1. finally(f)는 함수 f를 중복해서 쓸 필요가 없기때문에 .then(f, f)보다 문법 측면에서 편리하다.

 

Promise chaining(여러개의 Promise 연결하기)

then()메서드를 사용하면 새로운 Promise 객체가 반환된다. 그것을 이용해 여러개의 Promise를 연결해 사용할 수 있다.

function getData() {
  return new Promise({
// ...});
}

// then() 으로 여러 개의 프로미스를 연결한 형식getData()
  .then(function(data) { // Promise의 result나 err를 받아오고
// ...})
  .then(function() { // 밑에서 그걸 또 사용하고
// ...})
  .then(function() { // 또 사용하고
// ...});
// setTimeout을 활용한 비동기 처리 예제

new Promise(function(resolve, reject){ 
  setTimeout(function() {
    resolve(1);
  }, 2000); // 1. 2초뒤 result로 1로 이행하는 Promise 
})
.then(function(result) { // 2. 첫번째 then에서 그 1의 result를 받아서 
  console.log(result);// 1 
	return result + 10; // 3. 1 + 10을 리턴하고 
})
.then(function(result) { // 4. 그 리턴값(11)을 받아서 
  console.log(result);// 11
	return result + 20;
})
.then(function(result) {
  console.log(result);// 31});

 

 

 

 

출처

https://shoney.tistory.com/entry/자바스크립트-콜백함수CallBack-예제를-통해-가장-쉽게-이해하기

https://joshua1988.github.io/web-development/javascript/promise-for-beginners/#promise가-뭔가요

https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/#콜백-함수로-비동기-처리-방식의-문제점-해결하기

https://ko.javascript.info/callbacks

Comments