select: Make promise cancellable.
This commit is contained in:
parent
03ebfaf7ab
commit
67012b6f4b
3 changed files with 36 additions and 23 deletions
|
@ -85,6 +85,9 @@ Returns a version of the channel that provides only write methods.
|
||||||
returns the channel of the first one that succeeds. Only the winning method is
|
returns the channel of the first one that succeeds. Only the winning method is
|
||||||
executed to completion—the other methods have no effect.
|
executed to completion—the other methods have no effect.
|
||||||
|
|
||||||
|
All of the methods can be cancelled before completion by calling `cancel` on the
|
||||||
|
promise returned from `select`.
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
|
|
||||||
Imagine you're at a party and your next conversation depends on whom you run
|
Imagine you're at a party and your next conversation depends on whom you run
|
||||||
|
|
49
lib/index.js
49
lib/index.js
|
@ -309,31 +309,34 @@ Channel.of = (...values) =>
|
||||||
Channel.isChannel = (arg) =>
|
Channel.isChannel = (arg) =>
|
||||||
prototype.isPrototypeOf(arg)
|
prototype.isPrototypeOf(arg)
|
||||||
|
|
||||||
Channel.select = (...methodPromises) => {
|
Channel.select = (...methodPromises) =>
|
||||||
const promise = new Promise((resolve, reject) => {
|
Object.assign(
|
||||||
methodPromises.forEach(async (promise) => {
|
new Promise((resolve, reject) => {
|
||||||
promise.prethen(() => {
|
methodPromises.forEach(async (promise) => {
|
||||||
// We've been given a heads-up that this method will complete first so
|
promise.prethen(() => {
|
||||||
// cancel the other method calls.
|
// We've been given a heads-up that this method will complete first so
|
||||||
methodPromises.forEach((other) => {
|
// 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)
|
||||||
})
|
})
|
||||||
|
}),
|
||||||
try {
|
{
|
||||||
await promise
|
cancel: () =>
|
||||||
} catch (exception) {
|
Promise.all(methodPromises.map((promise) => promise.cancel()))
|
||||||
reject(exception)
|
}
|
||||||
}
|
)
|
||||||
|
|
||||||
resolve(promise.channel)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return promise
|
|
||||||
}
|
|
||||||
|
|
||||||
// functional interface allowing full or partial application
|
// functional interface allowing full or partial application
|
||||||
//
|
//
|
||||||
|
|
|
@ -118,6 +118,13 @@ describe(`Channel`, function () {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it(`cancel`, async function () {
|
||||||
|
const channel = Channel()
|
||||||
|
Channel.select(channel.push(`cancelled`)).cancel()
|
||||||
|
const closed = Channel.of()
|
||||||
|
assert.equal(await Channel.select(channel.shift(), closed.shift()), closed)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe(`functional interface`, async function () {
|
describe(`functional interface`, async function () {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue