Promise ๊ฐœ๋…๋ถ€ํ„ฐ ํ™œ์šฉ๊นŒ์ง€
language/javascript

Promise ๊ฐœ๋…๋ถ€ํ„ฐ ํ™œ์šฉ๊นŒ์ง€

โ“ Promise
    - js์—์„œ ์ œ๊ณตํ•˜๋ฉฐ, ๋น„๋™๊ธฐ๋ฅผ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” object
    - ์ •ํ•ด์ง„ ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ ํ›„ ์„ฑ๊ณต ์‹œ ์„ฑ๊ณต ๋ฉ”์‹œ์ง€์™€ ๊ฒฐ๊ณผ๊ฐ’ ์ „๋‹ฌ
    - ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ ์‹œ ๋ฌธ์ œ ๋ฐœ์ƒ ์‹œ ์—๋Ÿฌ ์ „๋‹ฌ
    - ๋น„๋™๊ธฐ์ ์ธ ๊ฒƒ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด Callbackํ•จ์ˆ˜ ๋Œ€์‹ ์— ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

โ— Point
    - 1. State: process๊ฐ€ heavyํ•œ operation์„ ์ˆ˜ํ–‰ ์ค‘์ธ์ง€, ๊ธฐ๋Šฅ ์ˆ˜ํ–‰์„ ์„ฑ๊ณต/์‹คํŒจ ํ–ˆ๋Š”์ง€
    - 2. Producer(์ •๋ณด์ œ๊ณต์ž) / Consumer(์ •๋ณด์‚ฌ์šฉ์ž)์˜ ์ฐจ์ด์ 

 

  • Promise๋Š” class โžก new ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ƒ์„ฑ์ž: executor๋ผ๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ „๋‹ฌ
  • executor ์•ˆ์—์„œ๋Š” ๋‹ค์‹œ resolve์™€ reject ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ „๋‹ฌ
  • resolve: ๊ธฐ๋Šฅ ์ •์ƒ ์ˆ˜ํ–‰ ํ›„ ์ตœ์ข… ๋ฐ์ดํ„ฐ ์ „๋‹ฌ
  • reject: ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ ์ค‘ ๋ฌธ์ œ ๋ฐœ์ƒ ์‹œ ํ˜ธ์ถœ
  • Promise๋ฅผ ๋งŒ๋“œ๋Š” ์ˆœ๊ฐ„, executor๋Š” ๋ฐ”๋กœ ์‹คํ–‰๋œ๋‹ค. (์ฆ‰, ์‚ฌ์šฉ์ž๊ฐ€ ์š”๊ตฌํ–ˆ์„ ๋•Œ๋งŒ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ๋ผ๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค!)

 

1. Producer

1-1. Resolve

const promise = new Promise((resolve, reject) => {
    // doing some heavy work (network, read files)
    console.log('doing something...');
    setTimeout(() => {
        resolve('ellie');
    }, 2000);
});

1-2. Reject

  • ๋ณดํ†ต Error๋ผ๋Š” object๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ์ „๋‹ฌํ•œ๋‹ค.
const promise = new Promise((resolve, reject) => {
    // doing some heavy work (network, read files)
    console.log('doing something...');
    setTimeout(() => {
        //resolve('ellie');
        reject(new Error('no network'));
    }, 2000);
});

 

2. Consumer

  • then, catch, finally๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ’์„ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
  • promise๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž˜ ์ˆ˜ํ–‰๋œ ํ›„ ์ตœ์ข…์ ์œผ๋กœ resolve๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ๋œ ๊ฐ’์ด ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋œ๋‹ค.

2-1. Resolve์˜ ๊ฐ’์„ ๋ฐ›์•„์˜ค๋Š” ๊ฒฝ์šฐ

promise.then((value) => {
    console.log(value);
})

2-2. Reject์˜ ๊ฐ’์„ ๋ฐ›์•„์˜ค๋Š” ๊ฒฝ์šฐ

๊ฐ€) then์„ ์ด์šฉํ•ด์„œ ์„ฑ๊ณต์ ์ธ case๋งŒ ๋‹ค๋ฃจ๋Š” ๊ฒฝ์šฐ

promise.then((value) => {
    console.log(value);
})

 

๋‚˜) Error handling

  • then์„ ์ด์šฉํ•ด์„œ ์„ฑ๊ณต์ ์ธ case๋ฅผ ์ž˜ ๋‹ค๋ค˜๋‹ค๋ฉด, catch๋ฅผ ํ†ตํ•ด error ๋ฐœ์ƒ ์‹œ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ธ์ง€ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•œ๋‹ค.
  • Chaining: then์„ ํ˜ธ์ถœํ•˜๋ฉด Promise๋ฅผ returnํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ฑฐ๊ธฐ์„œ ๋‹ค์‹œ catch ํ˜ธ์ถœ ๊ฐ€๋Šฅ
promise
.then((value) => {
    console.log(value); // ์„ฑ๊ณตํ•œ ๊ฐ’
})
.catch(error => { // ์‹คํŒจํ•œ error
    console.log(error);
})

3-3. Resolve, Reject์™€ ์ƒ๊ด€์—†์ด ๋งˆ์ง€๋ง‰์— ๋ฌด์กฐ๊ฑด ํ˜ธ์ถœ๋˜๋Š” ๊ฒฝ์šฐ

promise
.then((value) => {
    console.log(value);
}).catch(error => {
    console.log(error);
})
.finally(() => {
    console.log('finally');
});

๊ฐ€) Resolve์ธ ๊ฒฝ์šฐ

๋‚˜) Reject์ธ ๊ฒฝ์šฐ

 

 

3. Promise chaining

  • then์€ ๊ฐ’์„ ๋ฐ”๋กœ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๋˜ ๋‹ค๋ฅธ ๋น„๋™๊ธฐ์ธ Promise๋ฅผ ์ „๋‹ฌํ•ด๋„ ๋œ๋‹ค!
const fetchNumber = new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000);
});

fetchNumber
.then(num => num * 2)
.then(num => num * 3)
.then(num => {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(num - 1), 1000);
    });
})
.then(num => console.log(num));
// ์ด 2์ดˆ ์†Œ์š”!

 

4. Error Handling

const getHen = () => new Promise((resolve, reject) => {
    setTimeout(() => resolve('๐Ÿ“'), 1000);
});

const getEgg = hen => new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error(`${hen} => ๐Ÿฅš`)), 1000);
});

const cook = egg => new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${egg} => ๐Ÿณ`), 1000);
});

getHen()
.then(getEgg) // .then(hen => getEgg(hen))
.catch(error => {
    return '๐Ÿž'; // getEgg์—์„œ ์—๋Ÿฌ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ๋Œ€์‹  ๋นต์„ ๋ฐ›์•„์˜จ๋‹ค!
}) // ํ•„์š”ํ•œ ๊ณณ์— ์ ์ ˆํ•œ ์ˆœ์„œ๋กœ ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ ์ค‘์š”
.then(cook) // .then(egg => cook(egg))
.then(console.log); // .then(meal => console.log(meal));

 

5. Callback to Promise

// Callback Hell example
class UserStorage {
    loginUser(id, password) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if(
                    (id === 'ellie' && password === 'dream') ||
                    (id === 'coder' && password === 'academy')
                ) {
                    resolve(id);
                } else {
                    reject(new Error('not found'));
                }
            }, 2000);
        });
    }
    
    getRoles(user) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if(user === 'ellie') {
                    resolve({name: 'ellie', role: 'admin'});
                } else {
                    reject(new Error('no access'));
                }
            }, 1000);
        });
    }
}

const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');

userStorage
.loginUser(id, password)
.then(userStorage.getRoles)
.then(user => alert(`Hello ${user.name}, you have a ${user.role} role`))
.catch(console.log);

 

 

 

์ฐธ๊ณ 

youtube ๋“œ๋ฆผ์ฝ”๋”ฉ by ์—˜๋ฆฌ

https://www.youtube.com/watch?v=JB_yU6Oe2eE&list=PLv2d7VI9OotTVOL4QmPfvJWPJvkmv6h-2&index=12