Javascript – Promise and Promise chain and 함수를 이용한 프로미스

Promise

먼저 동기/비동기 프로그래밍에 대한 개념적 이해가 조금은 있어야, Promise 를 조금 이해하기 쉽니다.
자세한건 검색을 통해 개념을 익히고, 간단하게  설명하자면 , 어떠한 일을 처리하기 위해 처리하는동안   프로세스가 멈춰 있느냐(동기) 아니면 처리를 실행해놓고 다음 처리를 계속해서 실행하느냐(비동기) 차이 이다.

ㆍPromise 구조

//  [STATS]

//  Pending   –  작업 처리중   : ‘처리중’ 또는 ‘계류중’의 뜻으로 transactoin이 미완료된 상태를 말합니다.,
//  Fulfilled    –  작업 완료 ,  FulFilled : 충족된

//  Rejected  –  작업 오류 ,  Reject    : 거절하다

 

// [PRODUCER] : resolve , reject
// const promisObj = new Promise( (resolve , reject ) => {  비동기 작업 및 동기작업 });
//                                 resolve : 성공시 호출할 콜백 함수
//                                 reject    : 실패시 호출할 콜백 함수
// [CONSUMER] : then  , catch , finally
// resolve 콜백함수 호출시 파리미터 값과 함께  .then  에 매핑되어 콜백
// reject    콜백함수 호출시 파리미터 값과 함께  .reject   함수는 catch 에 매핑되어 콜백
//  resolve , reject 콜백함수와 관계없이
// 아래와 같이 resolve 또는 reject  콜백이 호출되어 있지않으면 pending 상태로 계속 유지되므로,
// 반드시 resolve 또는 reject 콜백을 호출해줘야만 한다.

[Pending 상태의 프로미스 – resolve 또는 reject 가 구현되어 있지 않음 ]
function getPromise() {
return new Promise( (resolve , reject) => {
let rtnValue;
return rtvValue;
});

}

 

———————————————————————————————————————————–

function getData()
{
    return new Promise((resolve , reject) => {
        return “tesT”;
    })
}
const myData = getData(); 
console.log(myData)  // Promise {<pending>}

 

 


ㆍPromise 기본 구현
// PRODUCER 기본 생성하기
// new Promise 를 myPromise 에 할당과 동시에 실행됨

const myPromise = new Promise( (resolve , reject) => {
    setTimeout(()=>{
         let ran = parseInt(Math.random() * 10);    
         ran % 2 == 0 ? resolve(ran) : reject(ran);
      // resolve 실행시 CONSUMER 의 myPromise.then( ()=>{})  호출됨
       // reject    실행시 CONSUMER 의 myPromise.catch(()=>{}) 호출됨
      } ,2000)
})

// CONSUMER (then ,catch , finally) 추가하기
// CONSUMER 를 연결하고자 하는 프로미스 객체의 메소드 구현
// myPromise.then(~).catch( ~ ).finally( ~ );  아래와같이 구현가능

myPromise
.then
( val => {
        console.log(“then : ” + val);
})
.catch( val => {
         console.log(“error : ” + val);
})
.finally( ()=>{
         console.log(“promise finally,,,,,,,,,,,,,,,,,,,,,,,,,,”)
})

ㆍPromise 체인
 Promise().then( return 값 or 프로미스객체).then( return 값 or 프로미스객체).then();
★ Promise 체인으로 작업을  연결하여 값(또는 프로미스)을  계속하여 처리하기 위해서는  return 을 통해, 다음 then  콜백함수로 전달 하여야한다.

Promise 체인 #1
<!DOCTYPE html>
<head>
    <script language=”javascript”>

        ‘use strict’

        const myPromise = new Promise( (resolve , reject) => {

            console.log(“myPromise Start..”)

            let i = 10;
            setTimeout( ()=>{
                resolve(10);
            })
        })
   
        myPromise
        .then( (val)=>{
            console.log(“call 1st then : ” + val); // call 1st then : 10
            val++;
            return val;
        })
        .then((val) =>{
            console.log(“call 2nd then : ” + val); // call 2nd then : 11
            val = val + 10;
            return val;
           
        })
        .then( (val)=>{
            console.log(a);   // 없는 변수 a 를 사용하면 .catch 로 점프 후  finally는 실행함
// 프로세스 중단됨(아래 then 부터 실행안함) 
        })
        .then((val) =>{
            console.log(“call 3nd then : ” + val);  // call 3nd then : 21
            // nothing  return 
        })
        .then( (val) =>
        {
            console.log(“call 4th then : ” + val);  // calll 5th then : undefined
        })      
        .then( (val)=>{
            return new Error(“test”);                    // 오류를 던져도 .catch 로 이동하지않음
// reject 또는 then 안에 변수 오류로만 이동됨
        })
        .then( (val) =>
        {
            console.log(“get new Error : ” + val);  // get new Error : Error: test
            return { name : “new object”}
        })
        .then( (val) =>
        {
            console.log(“calll new object then : ” + val.name);  
        })      
        .catch( (val) => {           
            console.log(“raising Error”)
        })
        .finally( ()=>{
            console.log(“This object of finally”);
        })

    </script>
</head>
</html>

Promise 체인 #2
–  프로미스 Consumer 에서 promise chain 구성

const myPromiseChain = new Promise( (resolve , reject) => {

    setTimeout( () =>{

        let ran = parseInt(Math.random() * 10);
        if (ran <= 7)
            resolve(ran);  // 7보다 작으며   .then 의 콜백으로 호출 
        else
            reject(ran);     // 7 보다 크면   .catch 의 콜백으로 호출 
    } , 1000)
});
myPromiseChain
.then( (val)=>{
        console.log(val);
        setTimeout( () => {
                      console.log(“callback #1 : ” + val);
val++;
            } ,3000)
           return val; // ★ 처리한 값을 “리턴” 하여 다음 “then” 의 val 로 넘김
    })
.then((val)=>{
        console.log(“callback #2 : ” + val);
         val = val + 10;
         return val;   // ★ 처리한 값을 “리턴” 하여 다음 “then” 의 val 로 넘김
    })
.then( (val)=>{
        console.log(“callback #3 : ” + val);
val = val + 100;
        return val   // ★ 처리한 값을 “리턴” 하여 다음 “then” 의 val 로 넘김
    })
.then(  val => myPromiseChain// .then( (val) => return myPromiseChain;} 의 축약
                                                        // myPromiseChain 의 최초 resolve 할때의 값이 val 에 들어감
.then( (val) => {
        let innerPromise = new Promise( (resolve , reject) =>{
            setTimeout( () =>{
                resolve(“inner first Promise”);
            }
            ,1000)
        })

// Promise 객체를 리턴하면 다음 then 은 innerPromise 의 CONSUMER 가 된다.

         // 즉,  innerPromise.then( (val) => { ~ });

         return innerPromise;   //  ★ 처리한 후 새로 만들어진  프로미스를 리턴 하여 다음 “then” 으로 넘김
    })
.then( (val)=>{  // innerPromise.then( (val) => { ~ } ) 가됨
            console.log(val)
            return new Promise( (resolve , reject) => {
            setTimeout(()=>{
                resolve(“inner second Promise”);
            },500);
        })
    })
.then((val) => {
         console.log(` val is ${val}’)   
        console.log(“the Last Promise made return new Promise”)
    })    
.then((val) =>{

         console.log(` val is ${val}`);  // ★ 위에 then 에 return 이 없기때문에 undefined
        console.log(“it’s over promise”)
    })

.then(( ) =>{  // 전달받은 인자 val 이 없기때문에, 실행안되고 자동으로 catch로 jump

         console.log(` val is ${val}`);  
    })
.catch((val) => console.log(“Error : ” + val))

Promise 체인 #3
–  프로미스로 사용될 함수를  따로 할당하여 변수로 프로미스 호출 하여 체인구성

    ‘use strict’
    // 글 저장 → 완료 메세지 → 리스트 이동
    const save = () => {
        let idx = 0;
        const savePromise = new Promise( (resolve , reject) => {
            setTimeout( ()=> {
                idx = 1234;
                resolve(idx);
            } , 1000)
        });
        return savePromise;
    }
   
    /*

//  { , }  없이 1 줄로 코딩 할 경우 코딩할경우 자동으로 리턴됨

        const save = () => new Promise((resolve , reject) => {
            setTimeout( ()=> {resolve(1234)} , 3000);
        })

  위와 아래는 같음 ,

        const save = () => {
            return new Promise( (resolve , reject) => {
                setTime(()=> { resolve(1234)} , 3000);
            })
        }
    */
    const saveMessage = idx => {    // const saveMessage = (idx) = > { ~  }; 와 같음
                                                        // const saveMessage = function(idx) = { ~ }; 와 같음
                                                        // function saveMessage(idx) { ~ } 와 같음
         return new Promise( (resolve, reject) => {
            setTimeout( function() {
                console.log(“save complete and i got the idx :” + idx);
                resolve(idx);
            } , 1000)                
        })
    }
   
    const list = function(idx)
    {
        return new Promise( (resolve , reject) =>
        {
           setTimeout( ()=> {
               console.log(“board list..”)
               resolve(idx);
               
           },1000);
        });
    }
    const boardButtonSetting = (idx) => new Promise( (resolve , reject) => { resolve(idx) });
    const boardColorSetting   = (idx) => new Promise( (resolve , reject) => { resolve(idx) });
    const boardTitleSetting     = (idx) => new Promise( (resolve , reject) => { resolve(` add title of ${idx}`)});
    const boardImageSetting  = (idx) => new Promise( (resolve , reject) => { resolve(` add Image of ${idx}`)});
     save()
    .then( (idx)=>{
        console.log(“from the save() :” +  idx);       
        // lsaveMessageist 에 idx 전달 . 처리 후 saveMessage 에서 promise 객체 리턴
        return saveMessage(idx);
    })
    .then( (idx) => {
        console.log(“from the saveMessage() : ” + idx);
       
        // list 에 idx 전달 . 처리 후 list 에서 promise 객체 리턴
        return list(idx);
    })
    .then( (idx) => {    // 여기 then list.then() 
        console.log(“from the list() : ” + idx);
        // boardButtonSetting 에 idx 전달 , 처리 후 boardButtonSetting 에서 promise 객체 리턴
        return boardButtonSetting(idx);
    })
    .then( (idx ) => {    // 여기 then 은 boardButtonSetting.then()
        console.log(“from the boardButtonSetting() :” + idx);  
        return idx;
       
    })    
    .then( idx => {
        console.log(“just send idx :” + idx);
        return boardColorSetting(idx);   
    })
    // 넘기고/받는 파라미터가 (idx), (settingS) 처럼 1개일때 생략 가능하여 아래처럼 단축하여 코딩가능
    .then(boardImageSetting)   // .then( (idx) => boardTitleSetting(idx)) 와 같음 ★
    .then(boardTitleSetting)      //  .then( (settings) => boardImageSetting(settings)) 와 같음 ★
    .then( (settings) => console.log(settings));

답글 남기기

이메일 주소는 공개되지 않습니다.