2014년 12월 26일 금요일

Q.Promise(function(resolve,reject,notify) {...})에 대한 메모

개요
Q.Promise의 사용에 있어서 역할이 혼란스러워 정리를 해두고자 한다.

수순

 var promise = Q.Promise(function(resolve,reject,notify) {  
   ???  
 });  

상기 ???에 대해, resolve, reject, notify를 대입해 promise체인에 대한 동작을 확인한다.

1. return reject();

 promise.catch(  
     function(ex) {  
       console.log("catch");    
     })  
     .fail(function(ex) {  
       console.log("fail");    
     })  
     .then(function(data) {  
       console.log(data);  
     });  
결과 :
catch
undefined

 promise  
   .fail(function(ex) {  
     console.log("fail");      
   })  
   .then(function(data) {  
     console.log(data);    
   });  
결과 :
fail
undefined.

 promise  
   .then(function(data) {  
     console.log(data);
   })  
   .fail(function(ex) {  
     console.log("fail");
   })  
   .catch(function(ex) {  
     console.log("catch");
   });

결과 :
fail

 promise  
   .then(function(data) {  
     console.log(data);  
   })  
   .catch(function(ex) {  
     console.log("catch");  
   });  
결과:
catch

-> 에러를 분리해서 체이닝 할경우, 실패가 뒤로 가야하는것을 알 수 있다. 에러보다 뒤에있는 then은, 실행이 완료된 후 다음 동작을 의미한다. catch, fail을 then과 병용할때는 catch,fail이 then의 뒤에 붙을 필요가 있다. 그리고 이런 수순이 혼란스러울 정도라면 체이닝을 할게 아니라 then의 2,3번째 callback에서 호출해야 맞지 않을까?

 promise  
    .then(function(data) {  
      console.log(data);  
    },function(err) {  
      console.log("err");  
    })  
    .catch(function(ex) { // or fail  
      console.log("catch");  
    });  
결과
err
-> catch/fail가 불려지지 않는다.

2. throw new Error("msg");
var promise = Q.Promise(function(resolve,reject,notify) {  
   throw new Error("test throw");  
});  

 promise  
    .then(function(data) {  
      console.log(data);
      res.json(data);  
    })  
    .fail(function(ex) {  
      console.log("fail");  
    })  
    .catch(function(ex) {  
      console.log("catch");  
    });  
결과
fail

 promise  
    .then(function(data) {  
      console.log(data);
      res.json(data);  
    })  
    .catch(function(ex) {  
      console.log("catch");  
    });  
결과
catch
-> throw역시 fail로 catch된다.

3. 그 외, notify
 var promise = Q.Promise(function(resolve,reject,notify) {  
   console.log("call");  
   notify(1); // some progressive  
   notify(2); // some progressive  
   return resolve("Apple");
});  

promise  
    .then(function(data) {  
      console.log(data);  
    },function(err) {  
      console.log("err");  
    },function(notification) {  
      console.log(notification);  
    })  
    .fail(function(ex) {  
      console.log("catch");  
    });  
결과
Apple
-> 1,2 notify가 호출되지 않았다...?

var promise = Q.Promise(function(resolve,reject,notify) {  
   
    Q.delay(1000)
     .then(function() {  
       notify(1);  
     })
     .delay(1000)
     .then(function() {  
       notify(2);
     })
     .then(function() {  
       resolve("apple");  
     });  
 });  

promise
    .then(function(data) {  
      console.log(data);
      res.json(data);
    },function(err) {  
      console.log("err");
      res.json(err);
    },function(notification) {  
      console.log(notification);
    });  
결과
1
2
apple
-> 각 결과가 1초 간격을 두고 불러졌다. 비동기에서만 notify가 반응하는듯 하다.

var promise = Q.Promise(function(resolve,reject,notify) {  
    Q.fcall(function() {  
      throw new Error("throw in another call stack");  });  
      return resolve("data");  
    });  

promise  
    .then(function(data) {  
      console.log(data);
      res.json(data);
    })  
    .catch(function(ex) {  
      console.log("catch");
    });  
결과
data

당연히 다른 callstack에서 throw 한 내용에 대해서는 catch 하지 않는다.

var promise = Q.Promise(function(resolve,reject,notify) {  
     Q.fcall(function() {  
       return reject(new Error("throw in another call stack"));    
       resolve("data");  
     });  
   });  

promise
    .then(function(data) {  
       console.log(data);
       res.json(data);
    })  
    .catch(function(ex) {  
      console.log("catch");
    });  

다른 call stack에서의 에러 호출은 상기와 같은 느낌으로 실시해야하고, 이후의 코드가 실행되지 않게 하기위해 (throw가 그렇듯) return하여 흐름을 끊어줄 필요가 있다.

var promise = Q.Promise(function(resolve,reject,notify) {  
    Q.fcall(function() {  
      return reject(new Error("throw in another call stack"));
      resolve("data");  
    })
    .then(function() {  
      console.log("is this code called?");  
    });  
 });  
 promise
    .then(function(data) {  
      console.log(data);    res.json(data);  
     })  
    .catch(function(ex) {  
      console.log("catch");  
     });  
결과
is this code called?
catch

-> 아... 위에서 reject를 리턴했다고 다음 then이 실행되지 않는건 아닌가보다.

var promise = Q.Promise(function(resolve,reject,notify) {  
    Q.fcall(function() {  
      return reject(new Error("throw in another call stack"));
      resolve("data");
    }).then(function(info) {  
      console.log("is this code called?");
      console.log(info);
      return "dummy";  
    }).then(function(info) {  
      console.log(info);  
    });  
});  

promise
    .then(function(data) {  
      console.log(data);
      res.json(data);  
    })  
    .catch(function(ex) {  
      console.log("catch");
    });  
결과
is this code called?
undefined
dummy
catch

-> reject의 return값은 void인듯하다. 처음 info는 아무 정보도 가지고 있지 않다. 다음 info는 위에서 return한 값 "dummy"를 가지고 있다. 이들은 일종의 event chain으로 sync동작하게된다. 따라서 catch가 가장 마지막에 나오고 있다. 중간에 delay를 끼워 yield에 상당하는 동작을 하게되면 상황은 바뀌게 될것이다.

var promise = Q.Promise(function(resolve,reject,notify) {  
     Q.fcall(function() {  
       return reject(new Error("throw in another call stack"));
       resolve("data");
     }).then(function(info) {  
       console.log("is this code called?");
       console.log(info);
       return "dummy";
     }).delay(1)
     .then(function(info) {  
       console.log(info);
     });  
 });  

promise
    .then(function(data) {  
      console.log(data);
      res.json(data);  
    })  
   .catch(function(ex) {  
       console.log("catch");
    });  
결과
is this code called?
undefined
catch
dummy

-> 예를 들자면 이런느낌이다.

댓글 없음:

댓글 쓰기