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 = [];
                        forvar 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 [123];
    }).then(function(num) {
        console.log(num); // [1, 2, 3]
    });
 
    // Example 2
    adun.Promise.then(function() {
        return [123];
    }).each(function(num) {
        console.log(num); // 1, 2, 3
                          // 보강 필요
    });
 
 
 
 
 
 
</script>
cs


휴 내일 회사가면 완성되겠지

재귀를 써서 _id값 찾아서 연결리스트에 이어붙여주면 어케되겠지 슈발  

그나저나 ㅅㅈ 이색히는 for문안에 for문이 계속해서있는 비동기를 왜 쓴다는거야 슈발