value: Convert from a getter to a method.

This commit is contained in:
David Braun 2017-10-20 21:42:50 -04:00
parent 8ec8fdacb2
commit 5470201c79
No known key found for this signature in database
GPG key ID: 5694EEC4D129BDCF
3 changed files with 196 additions and 195 deletions

View file

@ -6,7 +6,7 @@
- [writeOnly() -> Channel](#writeonly---channel) - [writeOnly() -> Channel](#writeonly---channel)
- [Channel.select(promises) -> async channel](#channelselectpromises---async-channel) - [Channel.select(promises) -> async channel](#channelselectpromises---async-channel)
- [Examples](#examples) - [Examples](#examples)
- [value](#value) - [value()](#value)
- [Array-like Properties](#array-like-properties) - [Array-like Properties](#array-like-properties)
- [Channel](#channel) - [Channel](#channel)
- [Channel([bufferLength = 0]) -> Channel](#channelbufferlength--0---channel) - [Channel([bufferLength = 0]) -> Channel](#channelbufferlength--0---channel)
@ -71,11 +71,11 @@ switch (await Channel.select([
charlie.push(`Hi!`) charlie.push(`Hi!`)
])) { ])) {
case alice: case alice:
console.log(`Alice said ${alice.value}.`); console.log(`Alice said ${alice.value()}.`);
break; break;
case bob: case bob:
console.log(`Bob said ${bob.value}.`); console.log(`Bob said ${bob.value()}.`);
break; break;
case charlie: case charlie:
@ -108,11 +108,11 @@ closed.close();
switch (await Channel.select([alice.shift(), bob.shift(), closed.shift())]) { switch (await Channel.select([alice.shift(), bob.shift(), closed.shift())]) {
case alice: case alice:
console.log(`Alice said ${alice.value}.`); console.log(`Alice said ${alice.value()}.`);
break; break;
case bob: case bob:
console.log(`Bob said ${bob.value}.`); console.log(`Bob said ${bob.value()}.`);
break; break;
default: default:
@ -128,11 +128,11 @@ setTimeout(timeout.close, 1000);
switch (await Channel.select([alice.shift(), bob.shift(), timeout.shift())]) { switch (await Channel.select([alice.shift(), bob.shift(), timeout.shift())]) {
case alice: case alice:
console.log(`Alice said ${alice.value}.`); console.log(`Alice said ${alice.value()}.`);
break; break;
case bob: case bob:
console.log(`Bob said ${bob.value}.`); console.log(`Bob said ${bob.value()}.`);
break; break;
default: default:
@ -140,9 +140,9 @@ switch (await Channel.select([alice.shift(), bob.shift(), timeout.shift())]) {
} }
``` ```
## value ## value()
Set to the most recently `shift`ed value. This is useful when used in Return the most recently `shift`ed value. This is useful when used in
combination with `select`. combination with `select`.
# Array-like Properties # Array-like Properties

View file

@ -36,7 +36,7 @@ const Order = channel => {
const prototype = {}; const prototype = {};
const Channel = function(bufferLength = 0) { const Channel = function(length = 0) {
let buffered = 0; let buffered = 0;
let closed = false; let closed = false;
let lastValue; let lastValue;
@ -70,7 +70,7 @@ const Channel = function(bufferLength = 0) {
for ( for (
; ;
resolvedIndex < index.push || resolvedIndex < index.push ||
(resolvedIndex < pushes.length && buffered < bufferLength); (resolvedIndex < pushes.length && buffered < length);
resolvedIndex++ resolvedIndex++
) { ) {
const { cancelled, resolve } = pushes[resolvedIndex]; const { cancelled, resolve } = pushes[resolvedIndex];
@ -80,7 +80,7 @@ const Channel = function(bufferLength = 0) {
buffered++; buffered++;
} }
resolve(bufferLength); resolve(length);
} }
} }
@ -101,7 +101,8 @@ const Channel = function(bufferLength = 0) {
resolvedIndex -= index.push; resolvedIndex -= index.push;
}; };
const readOnly = Object.assign(Object.create(prototype), { const readOnly = Object.freeze(
Object.assign(Object.create(prototype), {
every: async (callbackfn, thisArg) => { every: async (callbackfn, thisArg) => {
for (;;) { for (;;) {
const value = await readOnly.shift(); const value = await readOnly.shift();
@ -241,7 +242,9 @@ const Channel = function(bufferLength = 0) {
} }
}, },
toString: () => `Channel(${bufferLength})`, toString: () => `Channel(${length})`,
value: () => lastValue,
values: async () => { values: async () => {
const array = []; const array = [];
@ -252,16 +255,11 @@ const Channel = function(bufferLength = 0) {
return array; return array;
} }
}); })
);
Object.defineProperties(readOnly, { const writeOnly = Object.freeze(
length: { get: () => bufferLength }, Object.assign(Object.create(prototype), {
value: { get: () => lastValue }
});
Object.freeze(readOnly);
const writeOnly = Object.freeze({
close: () => close: () =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
if (closed) { if (closed) {
@ -275,6 +273,8 @@ const Channel = function(bufferLength = 0) {
} }
}), }),
length,
push: function(value) { push: function(value) {
const { order, promise } = Order(this); const { order, promise } = Order(this);
order.value = value; order.value = value;
@ -283,7 +283,9 @@ const Channel = function(bufferLength = 0) {
order.reject(new Error(`Can't push to closed channel.`)); order.reject(new Error(`Can't push to closed channel.`));
} else if (value === undefined) { } else if (value === undefined) {
order.reject( order.reject(
new TypeError(`Can't push 'undefined' to channel, use close instead.`) new TypeError(
`Can't push 'undefined' to channel, use close instead.`
)
); );
} else if (arguments.length > 1) { } else if (arguments.length > 1) {
order.reject(new Error(`Can't push more than one value at a time.`)); order.reject(new Error(`Can't push more than one value at a time.`));
@ -296,10 +298,12 @@ const Channel = function(bufferLength = 0) {
}, },
writeOnly: () => writeOnly writeOnly: () => writeOnly
}); })
);
// Use Object.create because readOnly has a getter. return Object.freeze(
return Object.freeze(Object.assign(Object.create(readOnly), writeOnly)); Object.assign(Object.create(prototype), readOnly, writeOnly)
);
}; };
Channel.from = values => { Channel.from = values => {
@ -384,7 +388,10 @@ Channel.select = methodPromises =>
// Channel.slice(10)(Infinity)(channel) // Channel.slice(10)(Infinity)(channel)
const channel = Channel(); const channel = Channel();
const methods = Object.keys(channel).concat(Object.keys(channel.readOnly()));
const methods = Object.keys(channel).filter(
method => typeof channel[method] === `function`
);
methods.forEach(method => { methods.forEach(method => {
const bound = function(...args) { const bound = function(...args) {

View file

@ -63,6 +63,8 @@ describe(`Channel`, function() {
it(`isChannel`, function() { it(`isChannel`, function() {
assert(Channel.isChannel(Channel.of(0, 1, 2))); assert(Channel.isChannel(Channel.of(0, 1, 2)));
assert(!Channel.isChannel(Array.of(0, 1, 2))); assert(!Channel.isChannel(Array.of(0, 1, 2)));
assert(Channel.isChannel(Channel().readOnly()));
assert(Channel.isChannel(Channel().writeOnly()));
}); });
it(`of`, async function() { it(`of`, async function() {
@ -80,7 +82,7 @@ describe(`Channel`, function() {
})(); })();
assert.equal(await Channel.select([a.shift(), b.shift()]), b); assert.equal(await Channel.select([a.shift(), b.shift()]), b);
assert.equal(b.value, 0); assert.equal(b.value(), 0);
assert.equal(await a.shift(), 1); assert.equal(await a.shift(), 1);
assert.equal(await Channel.select([a.push(0), b.shift()]), a); assert.equal(await Channel.select([a.push(0), b.shift()]), a);
}); });
@ -294,7 +296,7 @@ describe(`Channel object`, function() {
assert.equal(readOnly.readOnly(), readOnly); assert.equal(readOnly.readOnly(), readOnly);
assert.equal(await readOnly.shift(), 1); assert.equal(await readOnly.shift(), 1);
assert.equal(readOnly.value, 1); assert.equal(readOnly.value(), 1);
assert.throws(() => { assert.throws(() => {
readOnly.frozen = false; readOnly.frozen = false;
@ -367,21 +369,13 @@ describe(`Channel object`, function() {
}); });
it(`value`, async function() { it(`value`, async function() {
const channel = Channel(); const channel = Channel(1);
(async () => { await channel.push(null);
await channel.push(0);
})();
await channel.shift(); await channel.shift();
assert.equal(channel.value, 0); assert.equal(channel.value(), null);
assert.throws(() => {
channel.value = 1;
});
channel.close(); channel.close();
await channel.shift(); await channel.shift();
assert.equal(channel.value, undefined); assert.equal(channel.value(), undefined);
}); });
it(`values`, async function() { it(`values`, async function() {