Simplify implementation of select
.
This commit is contained in:
parent
ea2cc74711
commit
3ff3031b1e
2 changed files with 37 additions and 37 deletions
68
lib/index.js
68
lib/index.js
|
@ -403,45 +403,45 @@ Channel.of = (...values) => Channel.from(values);
|
||||||
Channel.isChannel = arg =>
|
Channel.isChannel = arg =>
|
||||||
arg !== undefined && arg !== null && Object.getPrototypeOf(arg) === prototype;
|
arg !== undefined && arg !== null && Object.getPrototypeOf(arg) === prototype;
|
||||||
|
|
||||||
Channel.select = methodPromises =>
|
Channel.select = methodPromises => {
|
||||||
Object.assign(
|
if (!Array.isArray(methodPromises)) {
|
||||||
new Promise((resolve, reject) => {
|
throw new TypeError(`Channel.select: Argument must be an array.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectPromise = new Promise((resolve, reject) => {
|
||||||
|
methodPromises.forEach(async promise => {
|
||||||
try {
|
try {
|
||||||
methodPromises.forEach(async promise => {
|
promise.prethen(() => {
|
||||||
try {
|
// We've been given a heads-up that this method will complete first
|
||||||
promise.prethen(() => {
|
// so cancel the other method calls.
|
||||||
// We've been given a heads-up that this method will complete first
|
methodPromises.forEach(other => {
|
||||||
// so cancel the other method calls.
|
if (other !== promise) {
|
||||||
methodPromises.forEach(other => {
|
other.cancel();
|
||||||
if (other !== promise) {
|
|
||||||
other.cancel();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
await promise;
|
|
||||||
} catch (exception) {
|
|
||||||
reject(exception);
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
resolve(promise.channel);
|
|
||||||
} catch (exception) {
|
|
||||||
reject(
|
|
||||||
new TypeError(
|
|
||||||
`Channel.select accepts only promises returned by push & shift.`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await promise;
|
||||||
|
} catch (exception) {
|
||||||
|
reject(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(promise.channel);
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
reject(new TypeError(`Channel.select: Argument must be an array.`));
|
reject(
|
||||||
|
new TypeError(
|
||||||
|
`Channel.select accepts only promises returned by push & shift.`
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}),
|
});
|
||||||
{
|
});
|
||||||
cancel: () => Promise.all(methodPromises.map(promise => promise.cancel()))
|
|
||||||
}
|
return Object.assign(selectPromise, {
|
||||||
);
|
cancel: () => methodPromises.forEach(promise => promise.cancel())
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// functional interface allowing full or partial application
|
// functional interface allowing full or partial application
|
||||||
//
|
//
|
||||||
|
|
|
@ -98,6 +98,7 @@ describe(`Channel function`, function() {
|
||||||
it(`miscellaneous`, async function() {
|
it(`miscellaneous`, async function() {
|
||||||
const a = Channel();
|
const a = Channel();
|
||||||
const b = Channel();
|
const b = Channel();
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
await b.push(0);
|
await b.push(0);
|
||||||
await a.push(1);
|
await a.push(1);
|
||||||
|
@ -114,10 +115,9 @@ describe(`Channel function`, function() {
|
||||||
it(`allows for non-blocking selects`, async function() {
|
it(`allows for non-blocking selects`, async function() {
|
||||||
const a = Channel();
|
const a = Channel();
|
||||||
const b = Channel();
|
const b = Channel();
|
||||||
|
const closed = Channel.of();
|
||||||
|
|
||||||
switch (
|
switch (await Channel.select([a.shift(), b.push(0), closed.shift()])) {
|
||||||
await Channel.select([a.shift(), b.push(0), Channel.of().shift()])
|
|
||||||
) {
|
|
||||||
case a:
|
case a:
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue