保誠-保戶業務員媒合平台
HelenHuang
2022-06-09 26a09f08cf1ed43c640879f23fdad56c5c9282f7
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
"use strict";
 
class QueueItem {
  constructor(onLoad, onError, dependentItem) {
    this.onLoad = onLoad;
    this.onError = onError;
    this.data = null;
    this.error = null;
    this.dependentItem = dependentItem;
  }
}
 
/**
 * AsyncResourceQueue is the queue in charge of run the async scripts
 * and notify when they finish.
 */
module.exports = class AsyncResourceQueue {
  constructor() {
    this.items = new Set();
    this.dependentItems = new Set();
  }
 
  count() {
    return this.items.size + this.dependentItems.size;
  }
 
  _notify() {
    if (this._listener) {
      this._listener();
    }
  }
 
  _check(item) {
    let promise;
 
    if (item.onError && item.error) {
      promise = item.onError(item.error);
    } else if (item.onLoad && item.data) {
      promise = item.onLoad(item.data);
    }
 
    promise
      .then(() => {
        this.items.delete(item);
        this.dependentItems.delete(item);
 
        if (this.count() === 0) {
          this._notify();
        }
      });
  }
 
  setListener(listener) {
    this._listener = listener;
  }
 
  push(request, onLoad, onError, dependentItem) {
    const q = this;
 
    const item = new QueueItem(onLoad, onError, dependentItem);
 
    q.items.add(item);
 
    return request
      .then(data => {
        item.data = data;
 
        if (dependentItem && !dependentItem.finished) {
          q.dependentItems.add(item);
          return q.items.delete(item);
        }
 
        if (onLoad) {
          return q._check(item);
        }
 
        q.items.delete(item);
 
        if (q.count() === 0) {
          q._notify();
        }
 
        return null;
      })
      .catch(err => {
        item.error = err;
 
        if (dependentItem && !dependentItem.finished) {
          q.dependentItems.add(item);
          return q.items.delete(item);
        }
 
        if (onError) {
          return q._check(item);
        }
 
        q.items.delete(item);
 
        if (q.count() === 0) {
          q._notify();
        }
 
        return null;
      });
  }
 
  notifyItem(syncItem) {
    for (const item of this.dependentItems) {
      if (item.dependentItem === syncItem) {
        this._check(item);
      }
    }
  }
};