<commit_before>---
title: "…from Data.Task"
prev_doc: v2.0.0/migrating/from-data.maybe
next_doc: v2.0.0/migrating/from-data.validation
---

The `Task` structure went through many changes in Folktale 2 to make automatic resource management of asynchronous computations safer and more robust. It also removes the need for the external `control.async` module, by natively supporting combining tasks in the object itself. This page explains how to migrate from the old `Data.Task` to the new `Task` module. You can look at the [full documentation for the concurrency module](/api/v2.0.0/en/folktale.concurrency.html) for more detailed information.


## Contents
{:.no_toc}

* TOC
{:toc}


## Constructing

Previously, to construct a `Task`, you'd pass a computation to the constructor, and this computation would return the resources that were allocated by the task. A second function would take the resources allocated and collect them:

{% highlight js %}
const Task = require('data.task');

function delay(ms) {
  return new Task((reject, resolve) => {
    return setTimeout(
      () => { resolve() },
      ms
    );
  }, (timer) => {
    clearTimeout(timer);
  });
}
{% endhighlight %}

Now, when constructing a Task your computation receives an object that lets you change the state of the Task, and define functions to handle cancellations and deallocating resources. The new Task module also exposes the constructor as a regular function, so you don't use `new` anymore:

{% highlight js %}
const { task } = require('folktale/concurrency/task');

function delay(ms) {
  return task(resolver => {
    const timerId = setTimeout(
      () => { resolver.resolve() },
      ms
    );
    resolver.cleanup(() => {
      clearTimeout(timerId);
    });
  });
}
{% endhighlight %}


## Running tasks

Previously Tasks could be ran by invoking the `.fork(onFailure, onSuccess)` method and providing a callback for successes and failures. This put the burden of collecting resources on the caller of that function:

{% highlight js %}
const Task = require('data.task');

function delay(ms) {
  return new Task((reject, resolve) => {
    return setTimeout(
      () => { resolve() },
      ms
    );
  }, (timer) => {
    clearTimeout(timer);
  });
}

const resources = delay(1000).fork(
  (error) => {
    delay.cleanup(resources);
  },
  (value) => {
    delay.cleanup(resources);
  }
);
{% endhighlight %}

The new Folktale has improved the execution of Tasks by modelling the execution of a task with a `TaskExecution` object. This object tracks resources and automatically handles them for the user, and allows querying the value of the task or cancelling it easily:

{% highlight js %}
const { task } = require('folktale/concurrency/task');

function delay(ms) {
  return task(resolver => {
    const timerId = setTimeout(
      () => { resolver.resolve() },
      ms
    );
    resolver.cleanup(() => {
      clearTimeout(timerId);
    });
  });
}

delay(100).run();
{% endhighlight %}


## Cancelling tasks

Previously there was no formal support for cancellations in Tasks. It was possible to abuse the resource tracking to send a cancellation signal, but that put a lot of burden on Task authors and Task consumers, in particular with more complex tasks and combinations — which would often introduce race conditions that were difficult to predict.<commit_msg>Adds docs on migrating from .fork, fixes data.task's example<commit_after>---
title: "…from Data.Task"
prev_doc: v2.0.0/migrating/from-data.maybe
next_doc: v2.0.0/migrating/from-data.validation
---

The `Task` structure went through many changes in Folktale 2 to make automatic resource management of asynchronous computations safer and more robust. It also removes the need for the external `control.async` module, by natively supporting combining tasks in the object itself. This page explains how to migrate from the old `Data.Task` to the new `Task` module. You can look at the [full documentation for the concurrency module](/api/v2.0.0/en/folktale.concurrency.html) for more detailed information.


## Contents
{:.no_toc}

* TOC
{:toc}


## Constructing

Previously, to construct a `Task`, you'd pass a computation to the constructor, and this computation would return the resources that were allocated by the task. A second function would take the resources allocated and collect them:

{% highlight js %}
const Task = require('data.task');

function delay(ms) {
  return new Task((reject, resolve) => {
    return setTimeout(
      () => { resolve() },
      ms
    );
  }, (timer) => {
    clearTimeout(timer);
  });
}
{% endhighlight %}

Now, when constructing a Task your computation receives an object that lets you change the state of the Task, and define functions to handle cancellations and deallocating resources. The new Task module also exposes the constructor as a regular function, so you don't use `new` anymore:

{% highlight js %}
const { task } = require('folktale/concurrency/task');

function delay(ms) {
  return task(resolver => {
    const timerId = setTimeout(
      () => { resolver.resolve() },
      ms
    );
    resolver.cleanup(() => {
      clearTimeout(timerId);
    });
  });
}
{% endhighlight %}


## Running tasks

Previously Tasks could be ran by invoking the `.fork(onFailure, onSuccess)` method and providing a callback for successes and failures. This put the burden of collecting resources on the caller of that function:

{% highlight js %}
const Task = require('data.task');

function delay(ms) {
  return new Task((reject, resolve) => {
    return setTimeout(
      () => { resolve() },
      ms
    );
  }, (timer) => {
    clearTimeout(timer);
  });
}

const delayTask = delay(1000);
const resources = delayTask.fork(
  (error) => {
    delayTask.cleanup(resources);
  },
  (value) => {
    delayTask.cleanup(resources);
  }
);
{% endhighlight %}

The new Folktale has improved the execution of Tasks by modelling the execution of a task with a `TaskExecution` object. This object tracks resources and automatically handles them for the user, and allows querying the value of the task or cancelling it easily:

{% highlight js %}
const { task } = require('folktale/concurrency/task');

function delay(ms) {
  return task(resolver => {
    const timerId = setTimeout(
      () => { resolver.resolve() },
      ms
    );
    resolver.cleanup(() => {
      clearTimeout(timerId);
    });
  });
}

delay(100).run();
{% endhighlight %}

To run arbitrary code in response to the result of executing the task, the `listen` method of `TaskExecution` is used in place of the functions one would pass to `Task.fork` before.

Where one used to write:

{% highlight js %}
const Task = require('data.task');

const one = new Task((reject, resolve) => resolve(1));

one.fork(
  (error) => { console.log('something went wrong') },
  (value) => { console.log(`The value is ${value}`) }
);
// logs "The value is 1"
{% endhighlight }

In Folktale 2 would be:

{% highlight js %}
const { task } = require('folktale/concurrency/task');

const one = task(resolver => resolver.resolve(1));

one.run().listen({
  onCancelled: () => { console.log('the task was cancelled') },
  onRejected: (error) => { console.log('something went wrong') },
  onResolved: (value) => { console.log(`The value is ${value}`) }
});
// logs "The value is 1"
{% endhighlight %}


## Cancelling tasks

Previously there was no formal support for cancellations in Tasks. It was possible to abuse the resource tracking to send a cancellation signal, but that put a lot of burden on Task authors and Task consumers, in particular with more complex tasks and combinations — which would often introduce race conditions that were difficult to predict.
{'fraction_non_alphanumeric': 0.11188901854012706, 'fraction_numerical': 0.005056398288603656, 'mean_word_length': 3.8454773869346734, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1878258', 'n_tokens_mistral': 2214, 'n_tokens_neox': 2102, 'n_words': 868}