Combines two tasks such that the resulting task assimilates the result of the first one to resolve.
This API is still experimental, so it may change or be removed in future versions. You should not rely on it for production applications.
Combines two tasks such that the resulting task assimilates the result of the first one to resolve.
Note that once a task finishes, the other task is cancelled. If the combined task is cancelled, both tasks are also cancelled.
As a convenience for combining a large or unknown amount of tasks, the
waitAny()
function in the concurrency/task
module preceives an array of Tasks to
"or" together.
const { task } = require('folktale/concurrency/task');
const delay = (ms) => task(
resolver => {
const timerId = setTimeout(() => resolver.resolve(ms), ms);
resolver.cleanup(() => {
clearTimeout(timerId);
});
}
);
const timeout = (ms) => task(
resolver => {
const timerId = setTimeout(() => resolver.reject(ms), ms);
resolver.cleanup(() => {
clearTimeout(timerId);
});
}
);
const result = await delay(20).or(timeout(300))
.run().promise();
$ASSERT(result == 20);
const result2 = await delay(200).or(timeout(100))
.run().promise().catch(e => `timeout ${e}`);
$ASSERT(result2 == 'timeout 100');
or(that) {
return new Task(resolver => {
let thisExecution = this.run(); // eslint-disable-line prefer-const
let thatExecution = that.run(); // eslint-disable-line prefer-const
let done = false;
resolver.onCancelled(() => {
thisExecution.cancel();
thatExecution.cancel();
});
const guard = (fn, execution) => (value) => {
if (!done) {
done = true;
execution.cancel();
fn(value);
}
};
thisExecution.listen({
onRejected: guard(resolver.reject, thatExecution),
onCancelled: guard(resolver.cancel, thatExecution),
onResolved: guard(resolver.resolve, thatExecution)
});
thatExecution.listen({
onRejected: guard(resolver.reject, thisExecution),
onCancelled: guard(resolver.cancel, thisExecution),
onResolved: guard(resolver.resolve, thisExecution)
});
});
}