1 | 'use strict'
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | const CLOSED = Promise.resolve()
|
11 |
|
12 | module.exports = class Result {
|
13 | constructor () {
|
14 | this._isClosed = false
|
15 | this._pendingPromises = []
|
16 | this._pendingVals = []
|
17 |
|
18 |
|
19 | }
|
20 |
|
21 | add (val) {
|
22 | if (this.isClosed) {
|
23 | throw new Error('cannot add() to a closed Result')
|
24 | }
|
25 |
|
26 | if (this._pendingPromises.length > 0) {
|
27 | this._finishPromises(val)
|
28 | } else {
|
29 | this._pendingVals.push(val)
|
30 | }
|
31 | }
|
32 |
|
33 | get isClosed () {
|
34 | return this._isClosed
|
35 | }
|
36 |
|
37 | get hasValues () {
|
38 | return this._pendingVals.length > 0
|
39 | }
|
40 |
|
41 | |
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 | then (res, rej) {
|
53 | if (this.hasValues) {
|
54 | const val = this._pendingVals.shift()
|
55 | const method = val instanceof Error ? 'reject' : 'resolve'
|
56 | return Promise[method](val).then(res, rej)
|
57 | }
|
58 |
|
59 | if (this.isClosed) {
|
60 |
|
61 | return CLOSED.then(res, rej)
|
62 | }
|
63 |
|
64 | const p = new Promise((resolve, reject) => {
|
65 | this._pendingPromises.push({ resolve, reject })
|
66 | })
|
67 |
|
68 | return p.then(res, rej)
|
69 | }
|
70 |
|
71 | close (val) {
|
72 | this.add(val)
|
73 | this._isClosed = true
|
74 | }
|
75 |
|
76 | _finishPromises (val) {
|
77 | const method = val instanceof Error ? 'reject' : 'resolve'
|
78 |
|
79 | let promise
|
80 | while ((promise = this._pendingPromises.shift())) {
|
81 | promise[method](val)
|
82 | }
|
83 | }
|
84 | }
|