medium
Version:
CSP-style channel library using ES7 async/await keywords
109 lines (98 loc) • 2.12 kB
JavaScript
const base = () => ({
unreleased: [],
push(put) {
this.unreleased.push(put)
},
shift() {
return this.unreleased.shift()
},
isEmpty() { return !this.unreleased.length }
})
const fixed = limit => ({
unreleased: [],
released: [],
release(put) {
this.released.push(put)
put.resolve(true)
},
push(put) {
if (this.released.length === limit) {
this.unreleased.push(put)
} else {
this.release(put)
}
},
shift() {
if (!this.released.length) return
var next = this.released.shift()
var waiting = this.unreleased.shift()
if (waiting) this.release(waiting)
return next
},
isEmpty() { return !this.released.length }
})
const dropping = limit => ({
released: [],
push(put) {
if (this.released.length < limit) {
this.released.push(put)
}
put.resolve(true)
},
shift() {
return this.released.shift()
},
isEmpty() { return !this.released.length }
})
const sliding = limit => ({
released: [],
push(put) {
if (this.released.length === limit) {
this.released = this.released.slice(1).concat([ put ])
} else {
this.released.push(put)
}
put.resolve(true)
},
shift() {
return this.released.shift()
},
isEmpty() { return !this.released.length }
})
const throttled = ms => ({
alwaysUse: true,
unreleased: [],
released: [],
buffer: null,
run: null,
polling: false,
intervalRef: null,
ensurePolling() {
if (this.intervalRef !== null) return
this.intervalRef = setInterval(() => {
this.process()
if (!this.unreleased[0]) {
clearInterval(this.intervalRef)
this.intervalRef = null
}
}, ms)
},
process() {
if (this.unreleased[0]) {
const put = this.unreleased.shift()
this.released.push(put)
put.resolve(true)
const take = this.channel.takes.shift()
if (take) this.run(this.channel, put, take)
}
},
push(put) {
this.unreleased.push(put)
this.ensurePolling()
},
shift() {
return this.released.shift()
},
isEmpty() { !this.released.length && !this.unreleased.length }
})
module.exports = { base, fixed, dropping, sliding, throttled }