What the Functional Programming???(feat. Promise) - adelakim5/fe-w4-martian GitHub Wiki
μ¬μ€ λλ classλ§ λ§λ€μ΄λ΄€μ§ κ°μ²΄μ§ν₯ νλ‘κ·Έλλ°λ€μ΄ μ½λλ₯Ό μ§λ³Έ μ μ μμκ³ , μ€νλ € ν¨μλ‘ μκ² μ§μ μ‘°ν©ν΄λκ°λκ² λ μ¬λ°λ κ·Έλ° λ μμ μ λν΄ μ΄μ©λ©΄ ν¨μνμ λ μ λ§λ μ¬λμΈκ±΄κ° μΆμλλ°... μ΄λ² λ―Έμ μ νλ©΄μ μ μΈμ μΌλ‘ μ½λλ₯Ό μ§ λ€λ κ²μ΄ κ½€ λ―μ€λ€λ κ²μ κΉ¨λ¬μλ€. (κ·Έλ κ² λμ°ν νΌμ’ μ΄ λμ΄κ°λ μ€μΈλ―..)
λ°λΌμ μ΄λ² λ―Έμ μ κΈ°νλ‘ ν¨μν νλ‘κ·Έλλ°μ λν΄ μ΄ν΄νλ κΉμ΄λ₯Ό μ‘°κΈ λ λμ΄κΈ°λ‘ ν΄λ³Έλ€!
λͺ©μ°¨
- μ΄λ² λ―Έμ μμ λ΄κ° μλν κ²λ€
- ν¨μν νλ‘κ·Έλλ°μ λλΌκ³ μκ°νλ?
- Promiseμ λν΄ κΉ¨λ¬μ κ²λ€
μ΄λ² λ―Έμ μμ λ΄κ° μλν κ²λ€
ꡬν κ³Όμ μμ μμ§κ΅¬λ ν μλλ€λ λ§μμ§λ§ μΌλ¨ λλ¦ κ΄λͺ©(?)ν λ§ν μλλ€μ μΆλ €λ³΄μλ€.
MyPromise
mdnμ Promiseλ₯Ό λ³΄κ³ μ§λλ°°κΈ°μ€λ¬μ΄ νλ‘λ―Έμ€λ₯Ό λ§λ€μ΄λ³΄κ³ μΆμλλ°, λ΄ μλμΌλ‘ νμ ν λΆμ‘±ν κ² κ°μμ γ γ
μ¬μ€μ then()
, catch()
λ§ μ¬μ©νλ νμ νλ‘λ―Έμ€λ₯Ό ꡬννλ€.
const pipe = (...fns) => (acc) => fns.reduce((a, f) => f(a), acc);
// resolveλ‘ λ€μ΄μ¨ accκ° thenμΌλ‘ λ€μ΄μ€λ callbackν¨μλ€μ μν΄ μλ‘μ΄ κ°μΌλ‘ μ°μ¬μ§λλ‘ νλ ν¨μ
export default class MyPromise {
constructor(fn) {
this.cbList = [];
this.catchCb = (e) => {
throw e;
};
// fulfilled, rejected
this.state = "pending";
setTimeout(() => {
try {
this.state = "fulfilled";
fn(pipe(...this.cbList), this.catchCb);
} catch (e) {
this.state = "rejected";
this.catchCb(e);
}
}, 0);
}
then(callback) {
this.cbList.push(callback);
return this;
}
catch = (callback) => {
this.catchCb = callback;
return this;
};
}
- MyPromiseλ₯Ό μμ±ν λ resolveμ λ€μ΄μ¨ λ¦¬ν΄ κ°μ pipeν¨μλ₯Ό ν΅ν΄ thenμμ λ€μ΄μ¨ μ½λ°±ν¨μλ€μ΄ λͺ¨μΈ cbListμ ν¨μλ€μ μμ°¨μ μΌλ‘ κ±°μΉλ©° 리ν΄νλ€.
- MyPromiseμ μνλ
fulfilled
- MyPromiseμ μνλ
- λ°λ©΄ rejectλ‘ λ€μ΄μ¨ κ°(reason)μ catchν¨μλ₯Ό ν΅ν΄ catchCbλ‘ λ±λ‘νκ³ , μλ¬κ° λ¬μ λ νΈμΆνλ€.
- MyPromiseμ μνλ
rejected
- MyPromiseμ μνλ
adela
function ν¨μν νλ‘κ·Έλλ°μ νΉμ§ μ€ νλλ μ¬μ΄λμ΄ννΈκ° μλλ‘, μμν¨μλ€λΌλ¦¬μ μ‘°ν©μΌλ‘ μΈμ λ λμΌν outputμ λ΄λ κ²μΈλ°, λ΄κ° ꡬνν λͺλͺ ν¨μλ€μ λ€λ₯Έ ν¨μλ₯Ό μμ‘΄νλ μμΌλ‘ ꡬμ±λμ΄μμλ€.
κ·Έλμ μλ κΏμ ν¨μλ₯Ό ν©μ±μμΌ μ ν¨μλ₯Ό λ΄λ ν¨μλ₯Ό μ§κ³ , μ΄κ±Έ ν λλ‘ λ΄κ° μμμ λ§ν κ·Έλ° ν¨μλ€μ μμ±ν΄λ΄λ λ‘μ§μ μ§κ³ μΆμλλ° μμ§μ λλ μλν κΏμΈ κ² κ°μκ³ ..
κ·Έλ³΄λ€ μ’ λ μμ λ¨μμ ν©μ±ν¨μ(?)λ₯Ό λ§λ€μ΄λ³΄μλ€.
const adela = (f, ...fns) => (...args) =>
args.length
? f(
...fns.reduce((acc, fn, i) => {
acc.push(fn(args[i]));
return acc;
}, [])
)
: f(...fns);
μ΄λ¦μ λλ‘ μ§μκΉ νλλ°, μ΄λ 컀λ§μ κ²μν΄μ νκ³ μλ ν°λΌ.. 컀리λ μ¬λ μ΄λ¦μΈλ°, λλ κ·Έλ₯ λ΄ μ΄λ¦μΌλ‘ ν¨μλ₯Ό λ§λ€μλ€ γ γ γ γ
μ ν¨μλ λ€μκ³Ό κ°μ΄ μ¬μ©ν μ μλ€.
const findTarget = (elements, capital) => Object.entries(elements).find((item) => item[1].dataset.id === capital);
const getHTMLElements = (className) => document.querySelectorAll(`.${className}`);
const capital = (letter) => letter.toUpperCase();
// ...
const target = adela(findTarget, getHTMLElements, capital)("line__text", letter);
νμ΄μ°λ©΄ μλμ κ°λ€.
const elements = getHTMLElements("line__text");
const capital = capital(letter);
const target = findTarget(elements, capital);
// === const target = adela(findTarget, getHTMLElements, capital)("line__text", letter);
μ΄λ°μμΌλ‘ ν¨μ μμμ λ€λ₯Έ ν¨μλ₯Ό λ€λ₯Έ μΈμμ ν¨κ» νΈμΆν΄μ λ§λ μΈμλ₯Ό λ°κ³ μΆμ λ μ¬μ©νλ ν¨μμ΄λ€. μ‘°κΈ λ³΅μ‘ν λλλ μμ§ μμ§λ§, μλν΄λ³΄μλ€!
μ΄λ κ² ν¨μ ν©μ±μ λν μ΄λ§μ΄ λΆνμ€λ₯΄λ€ 보λ, ν¨μν νλ‘κ·Έλλ°μ 곡λΆνκ³ μΆμ μκ°μ΄ μμκΈ° μμνλ€.
ν¨μν νλ‘κ·Έλλ°μ λλΌκ³ μκ°νλ?
ν¨μλ€μ μ‘°ν©? ν¨μλ€μ μ§ν©?
ν¨μλ€ κ°κ³ μ¬κΈ°λ€ μ°κ³ μ κΈ°λ€ μ°λλ°, μ¬μ€ μΈμλ§ μ ννκ² κ°μ Έλ€ μ£Όλ©΄ λ΄κ° μμνλ κ²°κ³Όκ°μ 리ν΄νλ κ²?
λ°λΌμ ν¨μλ€μ΄ μμν¨μμ¬μΌνκ³ , μ μλ³μμ κ°μ μ°Έμ‘°κ° μ¬μ€μ ν¨μ μΈλΆμλ μ‘΄μ¬νμ§ μμ μ±λ‘ νλ‘κ·Έλλ°μ μΏ΅μμΏ΅μ νλ κ² ν¨μν νλ‘κ·Έλλ°μΈκ² κ°λ€. (κ·Έλμ μ μΈμ μ΄λΌκ³ λ§νλ κ² κ°κ³ ..)
μνν μ½λ©μ¬μ μ λ§μ λΉλ¦¬λ©΄,
- λͺ λ Ήν: λλ μ΄κ±°νκ³ , λλ μ κ±°νκ³ , μ€λ μ μͺ½μ μλκ±°νκ³ , μ μΉκ΅¬λ μ μ΄μ΄μ΄μ΄κΈ°μ μλκ±° νλλ‘ ν΄
- μ μΈν: μ΄κ±°λ μ΄κ±°μΌ.
μ΄λ λ€λ³΄λ, ν¨μλ₯Ό "κ°"μΌλ‘ λ°λΌλ³Ό μ μμ΄μΌ νλ€.
κ°μΌλ‘ λ°λΌλ³Έλ€? κ·ΈλΌ λ€λ₯Έ ν¨μμ "μΈμ"λ‘ λ£μ΄μ€ μ μλ€. λ¬Όλ‘ λ¦¬ν΄λ κ°λ₯~ ν¨μ μμμ μλ‘μ΄ ν¨μ λ§λ€μ΄λ΄λ κ²λ κ°λ₯~
μ΄λ° λ΄μ©λ€μ μμκ°λ€λ³΄λ.. λ΄κ° κ°κ°νκ³ μλ Promiseμ λ¬Έμ κ° μμλ€λ κ²μ κΉ¨λ«κ² λμλ€.
Promiseμ λν΄ κΉ¨λ¬μ κ²λ€
κ·Έ μ μ λͺ¨λλλΌλ κ°λ μ λν΄ μμ£Ό μ΄μ§ μκ²λμλ€.
μ μΈλλ λ§μμ μνλ©΄,
- ν¨μν νλ‘κ·Έλλ°μμλ λͺ¨λλλ₯Ό μ€μνλ νλ‘κ·Έλλ°κ³Ό λͺ¨λλκ° μλ νλ‘κ·Έλλ°μ΄ μλ€.
- λͺ¨λλλ λ©μλλ₯Ό κ°μ§ "κ°"
- μ’ λ νμ μ μ€μνλ ν¨μν νλ‘κ·Έλλ°μμ μ¬μ©νλ "κ°"
ν¨μν νλ‘κ·Έλλ°μ ν¨μλ₯Ό ν©μ±νλ©° νλ‘κ·Έλλ°μ νκ² λλλ°,
f(g(x)) = f(g(x)) // μνμ μΈκ³μμ 무쑰건 μ΄κ²λ§ κ°λ₯
f(g(x)) = x // νμ€ μΈκ³μμ κ°λ μ΄λ° κ²½μ° μ‘΄μ¬
μ΄λ° μ΄μ λ‘ μμ ν ν¨μν©μ±μ μν΄μ λͺ¨λλκ° μ‘΄μ¬νλ€.
λͺ¨λλ?
[1] // λ°μ€ μμ μλ "κ°"
μ΄κ² λͺ¨λλ.
λͺ¨λλλ₯Ό ν©μ±νλ€λ λ§μ
const g = a => a + 1;
const f = a => a * a;
const m = [1].map(g).map(f); // 1μ gλ₯Ό μ€ννκ³ , fλ₯Ό μ€ννλ λͺ¨λλ
//
Promise === future λͺ¨λλ
const m = [1].map(g).map(f).forEach(a => console.log(a));
const p = Promise.resolve(1).then(g).then(f).then(a => console.log(a));
// Promise.resolve(1) === [1]
// Promise.reolve(1) === λͺ¨λλ
λ§μ½ xκ°μ λ¬Έμ κ° μκ²Όλ€λ©΄?
// example
f(g(x)) = [] // λΉλ°°μ΄μ΄ λ€μ΄μ΄
μ΄λ° κ²½μ°, μΌλ°μ μΌλ‘λ κ·Έλ₯ νλ¬κ°κ² λμλ€λ©΄,
νλ‘λ―Έμ€λ λ€μκ³Ό κ°μ΄ λ°κΏμ£ΌκΈ° μν΄ μκ²Όλ€.
f(g(x)) = g(x)
- g(x)λ₯Ό νλλ° μλ¬ λ°μ! => fλ μ€ν μνκ³ κ·Έλ₯ g(x)νκ²κ³Ό λκ°κ² λμκ°λ!
- μλ¬κ° λ°μν κ²½μ°μλ μ λ κ² μ€νμν¨λ€.
const fg = x => Promise.resolve(x).then(g).then(f);
fg(1).then(console.log); // 4 (μ μμ μΌλ‘ λμ)
fg("μλ¬λ·").catch(_ => "μλ¬μΌ...").then(console.log); // μλ¬
νλ‘λ―Έμ€λ₯Ό μ½λ°±μ§μ₯μ ν΄κ²°νκΈ° μν΄ μ 리ν΄μ μ°λ "κ°μ²΄"λΌκ³ μκ°νλ©΄ μλͺ»λ μκ°!
νλ‘λ―Έμ€λ νλ‘λ―Έμ€λ₯Ό κ°μΌλ‘ λ€λ£¨κΈ° μν΄ μ¬μ©λλ κ²!
- μ΄λ€ μΌμ΄ μΌμ΄λ μ§ λͺ¨λ₯΄λ ν¨κ³Όλ₯Ό κ°μΈλκ³ λλ μ΄λ° ννμ κ°μ΄λΌκ³ ν΄λκ³
- λΉλκΈ°μ μΈ μν©κ³Ό μ±κ³΅κ³Ό μ€ν¨λ₯Ό κ°μΌλ‘ λ€λ£¨λ λͺ¨λλ
- "κ°"μ
setTimeOutμΌλ‘ λκΈ°μ μΌλ‘ μ€νμν€λ κ²μ νλ¦μ΄μ§ "κ°"μ΄ μλλ€.
const delay = (time, val) => new Promise(resolve => setTimeout(() => resolve(a), time));
delay(100, 5).then(console.log);
const a = delay(100, 4); // κ°μ ν λΉ κ°λ₯
if(a instanceof Promise) {}; // aκ° λ¬΄μμΈμ§ νμΈ κ°λ₯
if(true) a.then(fn); // 쑰건μ λ°λΌ λμνκ² ν μ μμ
νλ‘λ―Έμ€λ₯Ό λ§λ€μ΄μ μ΄λ€ ν¨μμ μ λ¬νκ±°λ μ΄λ€ λ‘μ§κ³Ό ν¨κ» λ€λ£° μ μκΈ°μ μλ―Έκ° μλ κ²μ΄λ€.
const go1 = (a, f) => f(a);
go1(10, console.log); // 10;
go1(delay(100, 5), console.log); // μλ¬λ¨
μ go1
μ λ€μκ³Ό κ°μ΄ μμ ν μ μλ€.
const go1 = (a, f) => a instanceof Promsie ? a.then(f) : f(a); // aκ° νλ‘λ―Έμ€μ΄λ©΄ then(f)λ₯Ό, κ·Έλ μ§ μμΌλ©΄ f(a)λ₯Ό λ°ν