diff --git a/src/examples/computation.ts b/src/examples/computation.ts index 8068bff3191764eacce29e8cc12b56377410daee..467d9b62430ae3607965517fafbfdb985c9010b2 100644 --- a/src/examples/computation.ts +++ b/src/examples/computation.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Task, Run, Progress, Scheduler, now } from 'mol-task' +import { Task, Run, Progress, Scheduler, now, MultistepTask } from 'mol-task' export async function test1() { const t = Task.create('test', async () => 1); @@ -13,11 +13,17 @@ export async function test1() { } function messageTree(root: Progress.Node, prefix = ''): string { - if (!root.children.length) return `${prefix}${root.progress.taskName}: ${root.progress.message}`; + const p = root.progress; + if (!root.children.length) { + if (p.isIndeterminate) return `${prefix}${p.taskName}: ${p.message}`; + return `${prefix}${p.taskName}: [${p.current}/${p.max}] ${p.message}`; + } const newPrefix = prefix + ' |_ '; const subTree = root.children.map(c => messageTree(c, newPrefix)); - return `${prefix}${root.progress.taskName}: ${root.progress.message}\n${subTree.join('\n')}`; + if (p.isIndeterminate) return `${prefix}${p.taskName}: ${p.message}\n${subTree.join('\n')}`; + return `${prefix}${p.taskName}: [${p.current}/${p.max}] ${p.message}\n${subTree.join('\n')}`; + } function createTask<T>(delayMs: number, r: T): Task<T> { @@ -38,7 +44,7 @@ export function abortAfter(delay: number) { }); } -function testTree() { +export function testTree() { return Task.create('test o', async ctx => { await Scheduler.delay(250); if (ctx.shouldUpdate) await ctx.update({ message: 'hi! 1' }); @@ -60,6 +66,17 @@ function testTree() { }); } +const ms = MultistepTask('ms-task', ['step 1', 'step 2', 'step 3'], async (p: { i: number }, step) => { + await Scheduler.delay(250); + await step(0); + await Scheduler.delay(250); + await step(1); + await Scheduler.delay(250); + await step(2); + await Scheduler.delay(250); + return p.i + 3; +}) + export function abortingObserver(p: Progress) { console.log(messageTree(p.root)); if (now() - p.root.progress.startedTime > 1000) { @@ -67,11 +84,16 @@ export function abortingObserver(p: Progress) { } } +export function logP(p: Progress) { console.log(messageTree(p.root)); } + async function test() { try { //const r = await Run(testTree(), p => console.log(messageTree(p.root)), 250); - const r = await Run(testTree(), abortingObserver, 250); - console.log(r); + //const r = await Run(testTree(), abortingObserver, 250); + //console.log(r); + + const m = await Run(ms({ i: 10 }), logP); + console.log(m); } catch (e) { console.error(e); } diff --git a/src/mol-task/execution/observable.ts b/src/mol-task/execution/observable.ts index 8c184c180944438d788b63a0000311d596a8c9f8..196a434c98e51c15ec6e10057b02e55a387020aa 100644 --- a/src/mol-task/execution/observable.ts +++ b/src/mol-task/execution/observable.ts @@ -158,9 +158,9 @@ class ObservableRuntimeContext implements RuntimeContext { } else { if (typeof update.canAbort !== 'undefined') progress.canAbort = update.canAbort; if (typeof update.current !== 'undefined') progress.current = update.current; - if (typeof update.isIndeterminate !== 'undefined') progress.isIndeterminate = update.isIndeterminate; if (typeof update.max !== 'undefined') progress.max = update.max; if (typeof update.message !== 'undefined') progress.message = update.message; + progress.isIndeterminate = typeof progress.current === 'undefined' || typeof progress.max === 'undefined'; } } diff --git a/src/mol-task/index.ts b/src/mol-task/index.ts index 66449f0fb16c3e632963118f26e69d1604e83eed..b46d873c2110ddc5d75902e1729f5ea87d2fa3da 100644 --- a/src/mol-task/index.ts +++ b/src/mol-task/index.ts @@ -11,6 +11,7 @@ import { ExecuteObservable } from './execution/observable' import { Progress } from './execution/progress' import { now } from './util/now' import { Scheduler } from './util/scheduler' +import { MultistepTask } from './util/multistep' // Run the task without the ability to observe its progress. function Run<T>(task: Task<T>): Promise<T>; @@ -21,4 +22,4 @@ function Run<T>(task: Task<T>, observer?: Progress.Observer, updateRateMs?: numb return ExecuteSynchronous(task); } -export { Task, RuntimeContext, Progress, Run, now, Scheduler } \ No newline at end of file +export { Task, RuntimeContext, Progress, Run, now, Scheduler, MultistepTask } \ No newline at end of file diff --git a/src/mol-task/task.ts b/src/mol-task/task.ts index 0ce5ca40bf65ef59de655b3ecdf39d4a2b12abec..5daab3d3437b4f0dab84e758285de109864f91f9 100644 --- a/src/mol-task/task.ts +++ b/src/mol-task/task.ts @@ -40,6 +40,8 @@ namespace Task { max: number } + export type Provider<P, T> = (params: P) => Task<T> + let _id = 0; function nextId() { const ret = _id; diff --git a/src/mol-task/util/multistep.ts b/src/mol-task/util/multistep.ts index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d56ce2e9009990b9a2884af7aa62bec7f96ca722 100644 --- a/src/mol-task/util/multistep.ts +++ b/src/mol-task/util/multistep.ts @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import { Task } from '../task' +import { RuntimeContext } from '../execution/runtime-context' + +export type MultistepFn<P, T> = + (params: P, step: (s: number) => Promise<void> | void, ctx: RuntimeContext) => Promise<T> + +function MultistepTask<P, T>(name: string, steps: string[], f: MultistepFn<P, T>, onAbort?: () => void): Task.Provider<P, T> { + return params => Task.create(name, async ctx => f(params, n => ctx.update({ message: `${steps[n]}`, current: n + 1, max: steps.length }), ctx), onAbort); +} + +export { MultistepTask } \ No newline at end of file