Select: Make compose-friendly by taking a known number of arguments.
This commit is contained in:
parent
d7355e17e1
commit
6ea2b8bafe
5 changed files with 24 additions and 22 deletions
23
doc/API.md
23
doc/API.md
|
@ -4,7 +4,7 @@
|
|||
- [close() -> async](#close---async)
|
||||
- [readOnly() -> Channel](#readonly---channel)
|
||||
- [writeOnly() -> Channel](#writeonly---channel)
|
||||
- [Channel.select(methods) -> async channel](#channelselectmethods---async-channel)
|
||||
- [Channel.select(promises) -> async channel](#channelselectpromises---async-channel)
|
||||
- [Examples](#examples)
|
||||
- [value](#value)
|
||||
- [Array-like Properties](#array-like-properties)
|
||||
|
@ -47,14 +47,13 @@ Return a version of the channel that provides only read methods.
|
|||
|
||||
Return a version of the channel that provides only write methods.
|
||||
|
||||
## Channel.select(methods) -> async channel
|
||||
## Channel.select(promises) -> async channel
|
||||
|
||||
Attempt to call multiple channel `methods` in parallel and return the channel of
|
||||
the first one that succeeds. Only the winning method is executed to
|
||||
completion—the other methods have no effect.
|
||||
Wait for the first channel method promise to succeed and then cancel the rest.
|
||||
Return the channel of the winning promise.
|
||||
|
||||
All of the methods can be cancelled before completion by calling `cancel` on the
|
||||
promise returned from `select`.
|
||||
All of the promises can be cancelled before completion by calling `cancel` on
|
||||
the promise returned by `select`.
|
||||
|
||||
### Examples
|
||||
|
||||
|
@ -62,11 +61,11 @@ Imagine you're at a party and your next conversation depends on whom you run
|
|||
into first: Alice, Bob, or Charlie.
|
||||
|
||||
```JavaScript
|
||||
switch (await Channel.select(
|
||||
switch (await Channel.select([
|
||||
alice.shift(),
|
||||
bob.shift(),
|
||||
charlie.push(`Hi!`)
|
||||
)) {
|
||||
])) {
|
||||
case alice:
|
||||
console.log(`Alice said ${alice.value}.`);
|
||||
break;
|
||||
|
@ -92,7 +91,7 @@ const increment = () => {
|
|||
return counter;
|
||||
};
|
||||
|
||||
await Channel.select(alice.push(increment()), bob.push(increment()));
|
||||
await Channel.select([alice.push(increment()), bob.push(increment())]);
|
||||
assert.equal(counter, 2);
|
||||
```
|
||||
|
||||
|
@ -103,7 +102,7 @@ channel to return immediately even if no other channels are ready:
|
|||
const closed = Channel();
|
||||
closed.close();
|
||||
|
||||
switch (await Channel.select(alice.shift(), bob.shift(), closed.shift())) {
|
||||
switch (await Channel.select([alice.shift(), bob.shift(), closed.shift())]) {
|
||||
case alice:
|
||||
console.log(`Alice said ${alice.value}.`);
|
||||
break;
|
||||
|
@ -123,7 +122,7 @@ You can also arrange it so that the `select` completes within a timeout:
|
|||
const timeout = Channel();
|
||||
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:
|
||||
console.log(`Alice said ${alice.value}.`);
|
||||
break;
|
||||
|
|
|
@ -300,7 +300,7 @@ Channel.of = (...values) => Channel.from(values);
|
|||
|
||||
Channel.isChannel = arg => prototype.isPrototypeOf(arg);
|
||||
|
||||
Channel.select = (...methodPromises) =>
|
||||
Channel.select = methodPromises =>
|
||||
Object.assign(
|
||||
new Promise((resolve, reject) => {
|
||||
methodPromises.forEach(async promise => {
|
||||
|
|
|
@ -18,7 +18,7 @@ it(`doubleselect`, async function() {
|
|||
// different channels.
|
||||
const sender = async (n, c1, c2, c3, c4) => {
|
||||
for (let i = 0; i < n; i++) {
|
||||
await Channel.select(c1.push(i), c2.push(i), c3.push(i), c4.push(i));
|
||||
await Channel.select([c1.push(i), c2.push(i), c3.push(i), c4.push(i)]);
|
||||
}
|
||||
|
||||
c1.close();
|
||||
|
|
|
@ -24,11 +24,11 @@ it(`select`, async function() {
|
|||
let i = 0;
|
||||
|
||||
do {
|
||||
switch (await Channel.select(
|
||||
switch (await Channel.select([
|
||||
a.push(GetValue()),
|
||||
b.push(GetValue()),
|
||||
closed.shift()
|
||||
)) {
|
||||
])) {
|
||||
case a:
|
||||
i++;
|
||||
a = Channel();
|
||||
|
|
|
@ -89,10 +89,10 @@ describe(`Channel`, function() {
|
|||
await a.shift();
|
||||
})();
|
||||
|
||||
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(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);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -102,7 +102,7 @@ describe(`Channel`, function() {
|
|||
const nonBlocking = Channel();
|
||||
nonBlocking.close();
|
||||
|
||||
switch (await Channel.select(a.shift(), b.push(0), nonBlocking.shift())) {
|
||||
switch (await Channel.select([a.shift(), b.push(0), nonBlocking.shift()])) {
|
||||
case a:
|
||||
assert(false);
|
||||
break;
|
||||
|
@ -119,9 +119,12 @@ describe(`Channel`, function() {
|
|||
|
||||
it(`cancel`, async function() {
|
||||
const channel = Channel();
|
||||
Channel.select(channel.push(`cancelled`)).cancel();
|
||||
Channel.select([channel.push(`cancelled`)]).cancel();
|
||||
const closed = Channel.of();
|
||||
assert.equal(await Channel.select(channel.shift(), closed.shift()), closed);
|
||||
assert.equal(
|
||||
await Channel.select([channel.shift(), closed.shift()]),
|
||||
closed
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -251,7 +254,7 @@ describe(`Channel object`, function() {
|
|||
const channel = Channel();
|
||||
|
||||
return assertRejects(async () => {
|
||||
await Channel.select(channel.push(undefined));
|
||||
await Channel.select([channel.push(undefined)]);
|
||||
}, new TypeError(`Can't push 'undefined' to channel, use close instead.`));
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue