Skip to content
/ task Public

A data type similar to the Task monad for handling async operations.

Notifications You must be signed in to change notification settings

jordalgo/task

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Task (J-Task)

A javascript data type for async requests. Similar to data.task, fun-task, and flutures with some modifications. Published on NPM as "j-task"

Installing

npm install j-task

Quick Details

  • You can't complete a Task more than once e.g. you can't call sendFail and then call sendSuccess or cancel.
  • Functions passed to Task can optionally create a cancel (like above) otherwise cancel will be an no-op.
  • It's lazy! The function passed on Task creation is only called when run is invoked.
  • There is no error catching in this Task implementation. Errors are not thrown or caught from within a Task. There are failure values but these are not the same thing as errors -- think of them as "bad news".

Table of Contents


Simple Example

import TaskMaker from 'jordalgo-task';
const task = TaskMaker((sendFail, sendSuccess) => {
  const id = setTimeout(() => {
    sendSuccess(1);
  }, 1000);
  return () => { clearTimeout(id); };
});

const cancel = task.run(
  fail => {
    // never called;
  },
  success => {
    // success === 1
  }
);

Chaining

A chained Task waits for the first Task to finish successfully before the subsequent ones are run. If a previous Task in a chain fails then subsequent Tasks will not be run and will continue down the chain. If you would rather still call the Task producing functions on a Task failure use bichain, which will pass along failures to a Task producing function.

function getUser(id) {
  return TaskMaker((sendFail, sendSuccess) => {
    // AJAX request to get a user with id
    sendSuccess({ user });
  });
}

// will only get called in the chain below if getUser sends a success.
function getFollowers(username) {
  return TaskMaker((sendFail, sendSuccess) => {
    // AJAX request using username
    success([followers]);
  });
}

getUser()
.map(user => user.name)
.chain(getFollowers)
.run(
  fail => {},
  success => {
    // success === [followers] (if all went well)
  }
});

Cancelling

Cancellation functions are great if you have a need to cancel an async action that hasn't completed yet. Cancel functions are provided by the computation passed in when creating a Task.

function requestData() {
  return TaskMaker((sendFail, sendSuccess) => {
    const request = new XMLHttpRequest();
    request.onreadystatechange = function() {
      if (request.readyState === XMLHttpRequest.DONE) {
        if (request.status === 200) {
          var response = JSON.parse(request.response);
          sendSuccess(response);
        } else {
          sendFail('Could not fetch data: ' + request.status);
        }
      }
    };
    request.open('GET', 'http:///my-endpoint');
    request.send();
    // the cancellation function
    return () => { request.abort(); }
  });
}

const cancel = requestData().run((fail, success) => {
  // response handling code
  // this should not get called if cancel calls before the Task completes
  // and the computation provides a cancellation function like above
});

// oops, didn't need that data after all
cancel();

You can also cancel multiple chained Tasks even if one has already completed:

const cancel = getUser()
  .map(user => user.name)
  .chain(getFollowers)
  .run(
    fail => {},
    success => {
      // success === [followers] (if all went well)
    }
  });

// If you invoke cancel after the getUser Task has already completed, it will call the cancel function of getFollowers

Cacheing

A promise-like feature that allows you to hang on to values already processed within a Task. Computations don't get re-run.

var count = 0;
const task = TaskMaker((sendFail, sendSuccess) => {
  const id = setTimeout(() => {
    sendSuccess(++count);
  }, 1000);
  return () => { clearTimeout(id); };
});

const taskOnce = task.cache();

taskOnce.run(
    fail => {},
    success => {
      // success === 1
      // count === 1
    }
});
taskOnce.run(
    fail => {},
    success => {
      // success === 1
      // count === 1
    }
});

Parallel Tasks

Parallelize multiple Tasks. Returns an array of successes. If one of the Tasks sends a fail then the cancellation functions for all other Tasks (not yet completed) will be called.

var count = 0;
function createTask(to) {
  var order = ++count;
  return TaskMaker(sendFail, sendSuccess => {
    var id = setTimeout(() => {
      sendSuccess(order);
    }, to);
    return () => {
      clearTimeout(id);
    };
  });
}

TaskMaker.all([
  createTask(100),
  createTask(500),
  createTask(0)
]).run(
  fail => {},
  success => {
    // count === 3
    // success === [3, 1, 2]
  }
});

Specifications compatibility

Task is compatible with Fantasy Land and Static Land implementing:

How is this Task different than Data.Task or Fun-Task

  • This Task offers a cache method that allow you to treat Tasks more like promises so computations don't get called more than once if multiple parts of your code call run on an Task.
  • No special or magical error catching involved.

Data.task, fun-task, and this Task are pretty similar and should be fairly interchangeable for the basics.

Credits

A lot of code was inspired and stolen directly from flutures, data.task, and fun-task,

About

A data type similar to the Task monad for handling async operations.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published