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 콜백함수와 관계없이// 아래와 같이 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 에 할당과 동시에 실행됨
// 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>
<!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 부터 실행안함)
})
.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 안에 변수 오류로만 이동됨
// 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++;
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;
val = val + 100;
return val; // ★ 처리한 값을 “리턴” 하여 다음 “then” 의 val 로 넘김
})
.then( val => myPromiseChain) // .then( (val) => return myPromiseChain;} 의 축약
// myPromiseChain 의 최초 resolve 할때의 값이 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 줄로 코딩 할 경우 코딩할경우 자동으로 리턴됨
// { , } 없이 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));