티스토리 뷰

콜백함수와 프로미스의 차이

function add10(a, callback) {
  setTimeout(() => callback(a+10), 100);
}

add10(5, res=> {
  console.log(res);
}) // 15
function add20(a) {
  return new Promise(resolve => setTimeout(()=>resolve(a+20), 100))
}

add20(5).then(console.log); // 25
add20(5).then(add20).then(console.log); // 45

프로미스의 가장 중요한 특징은 콜백함수와 달리 결과를 값으로 받아 저장할 수 있다는 것이다. 프로미스를 받아 then으로 이어 또 다른 작업을 할 수 있기 때문에, 코드도 간결해질 뿐더러 비동기 프로그래밍을 안정적으로 수행한다.

 

값으로서의 프로미스 활용

  • 어떤 값을 함수에 넣어서 리턴하는 함수가 있다고 할 때, 만약 그 값이 비동기적으로 전달되면 어떨까?
const go1 = (a,f) => f(a);
const add5 = a => a + 5; 

console.log(go1(10, add5)); // 15

const delay100 = a => new Promise(resolve => setTimeout(()=>resolve(a), 100));

console.log(go1(delay100(10), add5)); // [object Promise]5 
  • delay100이라는 함수로 비동기적으로 값을 전달하면 제대로된 값을 출력하지 못한다.
const go1 = (a,f) => a instanceof Promise ? a.then(f) : f(a);

const add5 = a => a + 5; 

const delay100 = a => new Promise(resolve => setTimeout(()=>resolve(a), 100));

console.log(go1(delay100(10), add5)); 
// Promise {<pending>} 펼쳐보면 
// [[PromiseStatus]]: "resolved"
// [[PromiseValue]]: 15
// undefined 

const result = go1(delay100(10), add5);
result.then(console.log) 
// Promise {<pending>}
// 15
  • 이때 go1이라는 함수를 변경해서, 만약 그 값이 프로미스의 인스턴스인지 체크한 뒤 비동기 프로그래밍 해주면 동기적으로 값이 전달될 때나 비동기적으로 값이 전달될 때나 관계없이 똑같은 값을 출력할 수 있다.

 

함수 합성

// 합성 함수
const g = a => a + 1;
const f = a => a * a;

console.log(f(g(1))); // 4
console.log(f(g())); // NaN
// 값이 없어도 강제 합성이 되고 결과를 리턴

[1].map(g).map(f).forEach(r => console.log(r)); // 4
[].map(g).map(f).forEach(r => console.log(r)); // log nth

Promise.resolve(1).then(g).then(f).then(r=>console.log(r))
  • 어레이는 맵을 통해서 안전하게 함수를 합성 -> 유효하지 못한 효과가 리턴되는 것을 방지(모나드)
  • 프로미스는 then을 통해 안전하게 함수를 합성 -> 비동기적 상황을 효과적으로 다룸(그러나 값이 전달되지 않는 경우 NaN을 리턴함)

 

Kleisli Composition

  • Kleisli Composition: 오류가 있을 수 있는 상황에서 안전하게 함수를 합성
  • 스테이트가 변경되어 함수 합성에 오류가 있는 경우
var users = [
    { id: 1, name: 'aa'},
    { id: 2, name: 'bb'},
    { id: 3, name: 'cc'},
]

const getUserById = id => users.find(u => u.id === id);

const f = ({name}) => name;
const g = getUserById;

const fg = id => f(g(id));

users.pop();
users.pop();

fg(2); // error!
g(2); // undefined
// 오류가 있을 수 있는 상황에서 fg와 g는 다른 결과를 출력 
const fg = id => Promise.resolve(id).then(g).then(f); 

const getUserById = id => users.find(u => u.id === id) || Promise.reject('없어요');
  • 프로미스를 사용하여 합성하면 g(2), fg(2)는 동일하게 Promise {<rejected>: "없어요"} 를 출력한다.

'공부일지(TIL) > JavaScript' 카테고리의 다른 글

[TypeScript] 특징과 데이터 타입  (0) 2019.09.05
ES6 모듈 시스템  (0) 2019.08.09
useEffect 이해하기  (2) 2019.08.05
[자바스크립트] this와 함수 Context  (0) 2019.06.22
ES9 features  (0) 2019.04.16
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
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
글 보관함