A Promise library for android which follows Promise/A+ standard
Nearly, all android promise open-source projects offer us a tool, which has async-thread-execution being involved
into their component. I must say, it is good, since AsyncTask
is just like that - executing tasks in
a pre-built task-executors, or let user provide one for AsyncTask
. But I think, Promise should just focus on
async processing functions with callbacks, without making any extra thread or using executors to handle runnable
or Callable
process.
The Promise lib here dose not do any thread-making stuff, or not depends on any executors. It just produce a
Deferred
object, letting you decide when to resolve
a deferred or reject
a deferred. Then making then
on
a desired looper thread.
If you want your runnable to be running asynchronously, just make your own thread to take charge of running and
remember to resolve
or reject
the result.
While in thenable
method, you should supply us a resolver
which can turn the promise result into another promise
just like Promise in javascript.
And, The Promise lib here also provide us a lot of features that js promise owns too. Here is the example:
public class PromiseTest {
public static void main(String...args) {
Promise<Integer> p1 = Promise.make(new DirectFunction<Integer>() {
@Override
public void run(final Locker<Integer> locker) {
new Thread() {
public void run() {
try {
System.out.println("p1 is running");
Thread.sleep(5000);
} catch (InterruptedException e) {
locker.reject(e);
}
locker.resolve(100);
System.out.println("p1 is over");
}
}.start();
}
});
Promise<Object> px = Promise.make(new DirectFunction<Object>() {
@Override
public void run(Locker<Object> locker) {
locker.reject(new TimeoutException("timeout"));
}
}).exception(new ExceptionResolver<Object, TimeoutException>() {
@Override
public Object onCatch(TimeoutException exception) {
exception.printStackTrace();
throw Promise.newException(exception);
}
});
px.exception(new ExceptionPromiseResolver<Object, InterruptedException>() {
@Override
public Promise<Object> onCatch(InterruptedException exception) {
throw Promise.newException(new IOException());
}
});
Promise<Integer> p1p = p1.clone();
Promise<Integer> p2 = Promise.make(new DirectFunction<Integer>() {
@Override
public void run(final Locker<Integer> locker) {
new Thread() {
public void run() {
try {
System.out.println("p2 is running");
Thread.sleep(4000);
} catch (InterruptedException e) {
locker.reject(e);
}
locker.resolve(100);
System.out.println("p2 is over");
}
}.start();
}
});
ArrayList<Promise<?>> list = new ArrayList<Promise<?>>();
list.add(p1);
list.add(p1p);
list.add(p2);
Promise.race(list).then(new DirectResolver<Object, Void>() {
@Override
public Void resolve(Object newValue) {
System.out.println("race complete" + newValue);
return null;
}
@Override
public Void reject(Exception exception) {
return null;
}
});
p1.then(new DirectResolver<Integer, String>() {
@Override
public String resolve(Integer newValue) {
System.out.println(newValue);
return "p1 resolved";
}
@Override
public String reject(Exception exception) {
throw Promise.newException(exception);
}
}).then(new SimplePromiseResolver<String, Integer>() {
@Override
public Promise<Integer> resolve(String newValue) {
System.out.println(newValue);
return Promise.make(new DirectFunction<Integer>() {
@Override
public void run(final Locker<Integer> locker) {
new Thread() {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
locker.reject(e);
}
locker.resolve(3000);
}
}.start();
}
});
}
}).then(new SimpleResolver<Integer, Integer>() {
@Override
public Integer resolve(Integer newValue) {
System.out.println("then resolve a new value=" + newValue);
return null;
}
}).then(new SimpleResolver<Number, Integer>() {
@Override
public Integer resolve(Number newValue) {
return null;
}
});
// making a deferred, then use defer to propagate a promise
final PromiseDeferred<Integer> defer = PromiseDeferred.make();
final PromiseDeferred<String> defer2 = PromiseDeferred.make();
defer.promise().then(new SimpleResolver<Integer, Void>() {
@Override
public Void resolve(Integer newValue) {
System.out.println("Defer:::" + newValue);
return null;
}
}).exception(new ExceptionResolver<Void, NullPointerException>() {
@Override
public Void onCatch(NullPointerException exception) {
exception.printStackTrace();
return null;
}
}).exception(new ExceptionResolver<Void, TimeoutException>() {
@Override
public Void onCatch(TimeoutException exception) {
exception.printStackTrace();
return null;
}
});
new Thread() {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
defer.reject(e);
}
defer.reject(new TimeoutException("defer timeout"));
}
}.start();
Thenable<Integer> th = p1;
Thenable<Integer> th2 = th.then(new SimpleResolver<Number, Integer>() {
@Override
public Integer resolve(Number newValue) {
return 4;
}
});
Thenable<Number> th3 = th2.cast();
th3.then(new SimpleResolver<Number, String>() {
@Override
public String resolve(Number newValue) {
System.out.println(newValue);
return String.valueOf(newValue);
}
}).then(defer2);
PromiseFactory.create(new DirectFunction<String>() {
@Override
public void run(Locker<String> locker) {
locker.resolve("444");
}
}).make().then(defer2);
Promise<Integer> intPromise = Promise.resolve(5);
Promise<Integer> exPromise = Promise.reject(new Exception());
Promise<Integer> clonePromise = Promise.resolve(th);
Promise.all(intPromise, exPromise, clonePromise);
}
}
Promise.make
is a promise factory method which can make a new promisePromise.all
equals to javascriptPromise.all
Promise.race
equals to javascriptPromise.race
Promise.series
means running functions sequentiallyPromise.resolve
equals to javascriptPromise.resolve
Promise.reject
equals to javascriptPromise.reject
Promise.newException
is to wrap and convert any exception into an internal runtime exceptionPromise.timeout
is to make an n milli-seconds timeout promise
promise.then
equals to javascriptpromise.then
, we can resolve async/synchronizedpromise.getThen
can make a newDirectFunction
for making a new android promisepromise.exception
equals to javascriptpromise.catch
promise.finalResult
equals to javascriptpromise.done
promise.cast
can safely casting a Promise to a NEW Promise
in javascript, calling then method is as simple as promise.then(resolve, reject)
in java, it's not easy to generate two object-arguments, so let's make it simple, that we can call .then
like this
promise.then(resolver)
within which the resolver implements two method resolve
and reject
The Promise lib provides many pre-built resolvers, and all are based on DirectResolver
or PromiseResolver
.
The former returns a result directly while the latter returns a promise
DirectResolver
turns a result into a new onePromiseResolver
turns a result into a promiseSimpleResolver
andSimplePromiseResolver
only care about resolving the result, other than popping exceptions on rejectingExceptionResolver
andExceptionPromiseResolver
only focus on a specific type of exceptionFinalResolver
only processes the final stuff whenever it is resolved or rejectedDoneResolver
only processes the final stuff with two arguments: exception and resultDeferred
a specific resolver which will deliver the result to another deferred callback
PromiseDeferred.make
is a factory method which can make a deferred object extending fromPromise.Locker
who is also a specific resolver
resolve
equals to javascriptdefer.resolve
, usually used as a locker in promisereject
equals to javascriptdefer.reject
, usually used as a locker in promisedone
detect whether this deferred has been ever invoked resolve or rejectpost
equals to androidhandler.post
, using the internal handlerpostDelay
equals to androidhandler.postDelay
, using the internal handlerremoveCallbacks
equals to android 'handler.removeCallbacks', using the internal handlerpromise
equals to javascriptdefer.promise
, which will generate a promise object who is waiting for the deferred to be resolved
PromiseFactory.create
will make a promise factory with aDirectFunction
to implement
promiseFactory.run
is a function you should override when you create your own factory unless you use staticcreate
promiseFactory.make
is to make a new promise, each time you call this, therun(locker)
will be executed
Copyright 2016 tangye1234.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.