ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2. Promise
    JavaScript 2021. 6. 10. 17:28

     

     

    Promise is JavaScript object for asynchronous operfation.

    State : pending -> fulfilled or rejected

    Producer vs Consumer

     

     

    new Promise(executor)

    A Promise object is created using the new keyword and its constructor.

     

     

    1. Producer

    // when new Promise is created, the executor runs automatically.
    const promise = new Promise((resolve, reject) => {
        // doing some heavy work (network, read files)
        console.log('doing something...');
        setTimeout(() => {
            resolve('lexie');
           // reject(new Error('no network'));
        },2000);
    });

    This constructor takes a function, called the "executor function", as its parameter.

    This function should take two functions as parameters.

    The first of these functions (resolve) is called when the asynchronous task completes successfully and returns the results of the task as a value.

    The second (reject) is called when the task fails, and returns the reason for failure, which is typically an error object.

     

     

     

    2. Consumer : then, catch, finally

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

    then

    : After doing well in Promise, Run when the resolve function is called.

     

    catch

    : Process functions rejected by Promise using catch.

     

    finally

    : It is a function that is performed at the end.

     

     

     

    Promise Chaning

    The then method returns a Promise which allows for method chaining.

    If the function passed as handler to then returns a Promise, an equivalent Promise will be exposed to the subsequent then in the method chain. The below snippet simulates asynchronous code with the setTimeout function.

    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));

    => Expect the number 5 to come out in 2 sec.

     

    Promise.resolve('foo')
      // 1. Receive "foo", concatenate "bar" to it, and resolve that to the next then
      .then(function(string) {
        return new Promise(function(resolve, reject) {
          setTimeout(function() {
            string += 'bar';
            resolve(string);
          }, 1);
        });
      })
      // 2. receive "foobar", register a callback function to work on that string
      // and print it to the console, but not before returning the unworked on
      // string to the next then
      .then(function(string) {
        setTimeout(function() {
          string += 'baz';
          console.log(string); // foobarbaz
        }, 1)
        return string;
      })
      // 3. print helpful messages about how the code in this section will be run
      // before the string is actually processed by the mocked asynchronous code in the
      // previous then block.
      .then(function(string) {
        console.log("Last Then:  oops... didn't bother to instantiate and return " +
                    "a promise in the prior then so the sequence may be a bit " +
                    "surprising");
    
        // Note that `string` will not have the 'baz' bit of it at this point. This
        // is because we mocked that to happen asynchronously with a setTimeout function
        console.log(string); // foobar
      });
    
    

    => logs, in order:
    Last Then: oops... didn't bother to instantiate and return a promise in the prior then so the sequence may be a bit surprising
    foobar
    foobarbaz

     

     

     

    Error Handling

    const getHen = () => 
        new Promise((resolve, reject) => {
            setTimeout(() => resolve('🐓'), 1000);
        });
    const getEgg = hen => 
        new Promise((resolve, reject) => {
            setTimeout(() => reject(new Error(`error ! ${hen} => 🥚`)), 1000);
        });
    const cook = egg => 
        new Promise((resolve, reject) => {
            setTimeout(() => resolve(`${egg} => 🍳`), 1000);
        });
    
    getHen()
        .then(hen => getEgg(hen))
        .then(egg => cook(egg))
        .then(meal => console.log(meal));
    
    // more clean code
    getHen() 
        .then(getEgg)
        .catch(error => {
            return '🥖';
        })
        .then(cook)
        .then(console.log)
        .catch(console.log);

    Result

    I returned bread instead of eggs because there was an error in the process of getting eggs.

    So in conclusion, I can cook with bread.

     

     

     

    Let's change the last callback function code to Promise.

    Before (using callback)

    'use strict';
    
     class UserStorage {
         loginUser(id, password, onSuccess, onError){
             setTimeout(() => {
                if(
                    (id === 'lexie' && password === 'sehong') ||
                    (id === 'sehong' && password === 'lexie')
                ) {
                    onSuccess(id);
                } else {
                    onError(new Error('not found'));
                }
             },2000);
         }
    
         getRoles(user, onSuccess, onError){
            setTimeout(() => {
                if(
                    (user === 'lexie')
                ) {
                    onSuccess({ name: 'lexie', role: 'admin'});
                } else {
                    onError(new Error('not access'));
                }
             }, 1000);
         }
     }
    
     const userStorage = new UserStorage();
     const id = prompt('enter your id');
     const password = prompt('enter your password');
     userStorage.loginUser(
         id,
         password,
         user => {
             userStorage.getRoles(
                                    user, 
                                    userWithRole => {
                                        alert(`Hello ${userWithRole.name}, you have a ${userWithRole.role} role`)
                                    },
                                  error => console.log(error));
             },
         error => console.log(error)
     );
    
    

     

    After (using Promise)

    'use strict';
    
     // Callback Hell example -> Promise
     class UserStorage {
         loginUser(id, password){
             return new Promise((resolve, reject) => {
                setTimeout(() => {
                    if(
                        (id === 'lexie' && password === 'sehong') ||
                        (id === 'sehong' && password === 'lexie')
                    ) {
                        resolve(id);
                    } else {
                        reject(new Error('not found'));
                    }
                 },2000);
             })
         }
    
         getRoles(user){
             return new Promise((resolve, reject) => {
                setTimeout(() => {
                    if(user === 'lexie') {
                        resolve({ name: 'lexie', role: 'admin'});
                    } else {
                        reject(new Error('not 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);
    

    It has become cleaner and easier to read.

     

     

     

     

     

    'JavaScript' 카테고리의 다른 글

    reduce()  (0) 2021.06.11
    map()  (0) 2021.06.10
    forEach()  (0) 2021.06.10
    3. async & await  (0) 2021.06.10
    1. callback function - Synchronous & Asynchronous  (0) 2021.06.10

    댓글

Designed by Tistory.