1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> </body> </html> <script> (function() { var adun = window.adun = {}; adun.Promise = (function() { function Promise() { this._init(); } Promise.prototype._init = function() { this._success = this._eachSuccess = this._fail = this._id = null; this._tail = this; }; Promise.prototype._add = function(queue) { // 큐 + 연결리스트 자료구조를 사용한다. // 마지막에 추가된 Promise 인스턴스._next => 마지막에 추가된 Promise 인스턴스 this._tail._next = queue; // 연결리스트에서 꼬리는 항상 마지막에 추가된 Promise 인스턴스를 가리킨다. this._tail = queue; // 메서드 체이닝 return this; }; Promise.prototype.then = function(fn) { var queue = new adun.Promise(); queue._success = fn; return this._add(queue); }; Promise.prototype.each = function(fn) { var queue = new adun.Promise(); queue._eachSuccess = fn; return this._add(queue); }; Promise.prototype.error = function(fn) { var queue = new adun.Promise(); queue._fail = fn; return this._add(queue); }; Promise.prototype.call = function(arg) { var received, queue = this; // _fail 건너띄기 while( queue && (!queue._success && !queue._eachSuccess) ) { queue = queue._next; } if( !(queue instanceof adun.Promise) ) { return; } try { if( queue._success ) { received = queue._success(arg); } else if(queue._eachSuccess) { adun.Promise.ID = []; var a = []; for( var i = 0, len = arg.length ; i < len; ++i ) { a.push(adun.Promise.then(queue._eachSuccess(arg[i]))) } received = adun.Promise.parallel(a); } } catch(e) { console.log(queue._success) return queue.fail(e); } if( received instanceof adun.Promise ) { // 반환값이 Promise 인스턴스라면 라면 이어 삽입해준다. adun.Promise._insert(queue, received); } else if( queue._next instanceof adun.Promise ) { // 반환값이 연결리스트이고, 다음이 Promise 인스턴스라면 호출한다. queue._next.call(received); } }; Promise.prototype.fail = function(arg) { var result, error, queue = this; // _success 건너띄기 while( queue && !queue._fail ) { queue = queue._next; } if( queue instanceof adun.Promise ) { result = queue._fail(arg); queue.call(result); } else { error = new Error('실패'); error.arg = arg; throw error; } }; // Static Promise.ID = null; Promise.then = function(fn) { var queue = new adun.Promise().then(fn); // 타이머 함수를 이용하여 비동기성을 가진다. // (함수 스택이 모두 클리어되었을 때 실행된다.) queue._id = setTimeout(function() { queue.call(); }, 0); return queue; }; Promise._insert = function(queue, ins) { // 만약 현재 큐의 _next가 Promise의 인스턴스라면 블록에 진입 if( queue._next instanceof adun.Promise ) { // 연결리스트의 swap과 같다. ins._tail._next = queue._next; } // 현재 큐의 _next에 새로운 Promise의 인스턴스를 참조시킨다. queue._next = ins; }; Promise.parallel = function(arg) { var q = new adun.Promise(); q._id = setTimeout(function() { q.call(); }, 0); var progress = 0; var ret = Array.isArray(arg) ? [] : {}; var p = new adun.Promise(); var prop; for( prop in arg ) { progress ++; // 복사본을 즉시실행 바로 넘겨준다. (function(queue, name) { // 복사본.then(fn); queue.then(function(arg) { progress --; ret[name] = arg || ''; // 리턴된 값 if( progress <= 0 ) { p.call(ret); } }).error(function(err) { p.fail(err); }); clearTimeout(queue._id); queue._id = setTimeout(function() { queue.call(); }, 0); })(arg[prop], prop); } if( progress == 0 ){ p._id = setTimeout(function() { p.call(ret); }); } return q.then(function() { return p; }); }; return Promise; })(); })(); // Example 1 adun.Promise.then(function() { return 3; }).then(function(num) { console.log(num); // 3 }); // Example 2 adun.Promise.then(function() { return [1, 2, 3]; }).then(function(num) { console.log(num); // [1, 2, 3] }); // Example 2 adun.Promise.then(function() { return [1, 2, 3]; }).each(function(num) { console.log(num); // 1, 2, 3 // 보강 필요 }); </script> | cs |
휴 내일 회사가면 완성되겠지
재귀를 써서 _id값 찾아서 연결리스트에 이어붙여주면 어케되겠지 슈발
그나저나 ㅅㅈ 이색히는 for문안에 for문이 계속해서있는 비동기를 왜 쓴다는거야 슈발
댓글 0