# Android-Deferred

--------
Deferred is a fork of Ray Tsang's [JDeferred](https://github.com/jdeferred/jdeferred) library inspired in [JQuery](https://github.com/jquery/jquery)

The purpose of the library is to provide an easy-to-use implementation of promised for Android applications with an architecture based on pools. In Tuenti we have an architecture where the developer is the responsible of known in which thread pool should his code be executed, in a similar way to RxJava, we distinguish between **network**, **disk**, **computation** or **UI** work, and we wanted a Promise implementation that let us work in that way easily.

--------
## How to use

### Features
* Deferred object and Promise
* Promise callbacks
  * ```.then(…)```
  * ```.done(…)```
  * ```.fail(…)```
  * ```.progress(…)```
  * ```.always(…)```
* Multiple promises
  * ```.when(p1, p2, p3, …).then(…)```
* Callable and Runnable wrappers
  * ```.when(new Runnable() {…})```
* Uses Executor Service
* Java Generics support
  * ```Deferred<Integer, Exception, Double> deferred;```
  * ```deferred.resolve(10);```
  * ```deferred.reject(new Exception());```
  * ```deferred.notify(0.80);```


#### Promises and Deferred objects

##### How to create them
```java
Deferred<Integer, Exception, Void> deferred = deferredFactory.build();

deferred.resolve(1);

Promise<Integer, Exception, Void> promise = deferred.promise();

promise.done((Done.Immediately<Integer>) i -> System.out.println(i));
```  
As you can see, `Done.Immediately<Integer>` is the type of Done callback that we want to use, for the callbacks, you can use:

* **Immediately:** To be run in the same thread where the promise has been resolved.
* **UI:** To run it on UI thread.
* **Computation:** To run it on the computation pool.
* **Disk:** To run it on disk pool.
* **Network:** To run it on network pool.

##### They are asynchronous

The promises are asynchronous, the callbacks can be set before/after the promise is finished

```java
Deferred<String, Exception, Void> deferred = deferredFactory.build();

deferred.done((Done.UI<String>) result -> System.out.println(result));

deferred.resolve("Finish!");
```

##### Filter

```java
Deferred<Integer, Void, Void> deferred = deferredFactory.build();

deferred.resolve(1);

deferred.then((Done.Filter.Computation<Integer, Integer>) i -> i * 2)
    .done((Done.UI<Integer>) i -> System.out.println(i));
```

##### Pipe
```java
Deferred<Integer, Void, Void> deferred = deferredFactory.build();

deferred.resolve(1);

deferred.then((Computation<Integer, Integer, Exception, Void>) i ->
    deferredFactory.<Integer, Exception, Void>build().reject(new Exception()))
    .done((UI<Integer>) i -> System.out.println(i))
    .fail((Fail.UI<Exception>) e -> System.out.println("Uh oh!"));
```
##### All this can be combined together
```java
Deferred<Integer, Void, Void> deferred = deferredFactory.build();

deferred.resolve(1);

deferred.then((Done.Pipe.Computation<Integer, Integer, Exception, Void>) i -> {
  Deferred<Integer, Exception, Void> positiveDeferred = deferredFactory.build();
  positiveDeferred.resolveOrReject(i > 0, i, new Exception("Noooo"));
  return positiveDeferred;
})
    .then((Done.Filter.Computation<Integer, String>) i -> "Result is " + String.valueOf(i))
    .done((Done.UI<String>) i -> System.out.println(i))
    .fail((Fail.UI<Exception>) e -> System.out.println(e.getMessage()));
}
```
##### DeferredManager:
You can use a `DeferredManager` implementation, `DefaultDeferredManager` or your custom one to combine the execution of several promises

for example:
```java
DeferredManager dm = new DefaultDeferredManager();
Promise p1, p2, p3;
// initialize p1, p2, p3
dm.when(p1, p2, p3)
  .done(…)
  .fail(…)
```

Or use `sequentiallyRunUntilFirstDone` to execute sequentially the promises until one is resolved:

For this you must instantiate some objects implementing PromiseObjectTask<D, F, P>

for example:
```java
private PromiseObjectTask<Data, Exception, Void> getDataFromMemory() {
	return new PromiseObjectTask<Data, Exception, Void>() {
		@Override
		public Promise<Data, Exception, Void> run() {
			return inMemoryStorage.getData();
		}
	};
}

private PromiseObjectTask<Data, Exception, Void> getDataFromDisk() {
	return new PromiseObjectTask<Data, Exception, Void>() {
		@Override
		public Promise<Data, Exception, Void> run() {
			return diskStorage.getData();
		}
	};
}

private PromiseObjectTask<Data, Exception, Void> getDataFromAPI() {
	return new PromiseObjectTask<Data, Exception, Void>() {
		@Override
		public Promise<Data, Exception, Void> run() {
			return apiClientStorage.getData();
		}
	};
}

deferredManager.sequentiallyRunUntilFirstDone(getDataFromMemory(),
				getDataFromDisk(),
				getDataFromAPI());
```

or avoiding verbosity using lambdas or method references:
```java
deferredManager.sequentiallyRunUntilFirstDone(inMemoryStorage::getData,
				diskStorage::getData,
				apiClient::getData);
```

Also, you can use `lazyAnd` or `lazyOr` to execute promises sequentially until the boolean condition is achieved.

--------

## How to add to your project

<!-- Add `compile TODO` to your _build.gradle_ file. -->

The promises are created via a `DeferredFactory`, to create an instance of this class you should provide an implementation of `ExecutorProvider`, this class will is where you will tell Deferred in which pool you want to execute your code, for example:

```java

import java.util.concurrent.Executor;
import com.tuenti.deferred.ExecutorProvider;

public class MyExecutorProvider implements ExecutorProvider {

	private final Executor myExecutor = new Executor() {
		@Override
		public void execute(Runnable command) {
			command.run();
		}
	};

	@Override
	public Executor getUiExecutor() {
		return myExecutor;
	}

	@Override
	public Executor getComputationExecutor() {
		return myExecutor;
	}

	@Override
	public Executor getDiskExecutor() {
		return myExecutor;
	}

	@Override
	public Executor getNetworkExecutor() {
		return myExecutor;
	}
}


```