forked from cojs/busboy
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathresult.js
84 lines (69 loc) · 1.91 KB
/
result.js
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
'use strict'
// like a promise
// if a value is added, it is queued until the first then()
// if then() is called before a value is available,
// the returned promise is deferred
// and queued up for later resolution eg when the next value is available or the
// Result is completed.
const CLOSED = Promise.resolve()
module.exports = class Result {
constructor () {
this._isClosed = false
this._pendingPromises = []
this._pendingVals = []
// TODO Nice to have ...array argument -> add()
}
add (val) {
if (this.isClosed) {
throw new Error('cannot add() to a closed Result')
}
if (this._pendingPromises.length > 0) {
this._finishPromises(val)
} else {
this._pendingVals.push(val)
}
}
get isClosed () {
return this._isClosed
}
get hasValues () {
return this._pendingVals.length > 0
}
/**
* Requests the next value, wrapped in a promise.
* If no more values are available and the Result
* is closed, a Promise resolved to undefined is returned.
* Else, the returned promise will resolve or reject
* when the next value is added.
*
* @param {Function} res
* @param {Function} rej
* @return {Promise}
*/
then (res, rej) {
if (this.hasValues) {
const val = this._pendingVals.shift()
const method = val instanceof Error ? 'reject' : 'resolve'
return Promise[method](val).then(res, rej)
}
if (this.isClosed) {
// no more values will ever be available
return CLOSED.then(res, rej)
}
const p = new Promise((resolve, reject) => {
this._pendingPromises.push({ resolve, reject })
})
return p.then(res, rej)
}
close (val) {
this.add(val)
this._isClosed = true
}
_finishPromises (val) {
const method = val instanceof Error ? 'reject' : 'resolve'
let promise
while ((promise = this._pendingPromises.shift())) {
promise[method](val)
}
}
}