I’ve developed a promise library for java so let me introduce it.
Overview
- You can easily control asynchronous operations like JavaScript’s Promise.
- Supports both synchronous and asynchronous execution.
- All the examples presented in this article are here. https://github.com/riversun/java-promise-examples
Quick Look
Writing a Promise in Javascript
A typical example of using promise in JavaScript is:
Promise.resolve('foo')
.then(function (data) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
const newData = data + 'bar';
resolve(newData);
}, 1);
});
})
.then(function (data) {
return new Promise(function (resolve, reject) {
console.log(data);
});
});
console.log("Promise in JavaScript");
Enter fullscreen mode Exit fullscreen mode
Writing a Promise in java-promise
Write the same thing using java-promise
import org.riversun.promise.Promise;
public class Example {
public static void main(String[] args) {
Promise.resolve("foo")
.then(new Promise((action, data) -> {
new Thread(() -> {
String newData = data + "bar";
action.resolve(newData);
}).start();
}))
.then(new Promise((action, data) -> {
System.out.println(data);
action.resolve();
}))
.start();
System.out.println("Promise in Java");
}
}
Enter fullscreen mode Exit fullscreen mode
Syntax:
Yes,you can write in a syntax similar to JavaScript as follows:
Promise.resolve()
.then(new Promise(funcFulfilled1), new Promise(funcRejected1))
.then(new Promise(functionFulfilled2), new Promise(functionRejected2))
.start();
Enter fullscreen mode Exit fullscreen mode
Dependency
Maven
<dependency>
<groupId>org.riversun</groupId>
<artifactId>java-promise</artifactId>
<version>1.1.0</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode
Gradle
compile group: 'org.riversun', name: 'java-promise', version: '1.1.0'
Enter fullscreen mode Exit fullscreen mode
Quick Start
Execute sequentially by chained “then”
- Use Promise.then() to chain operations.
- Write your logic in Func.run(action,data).
- Start operation by Promise.start and run asynchronously(run on worker thread)
- Calling action.resolve makes the promise fullfilled state and passes the result to the next then
public class Example00 {
public static void main(String[] args) {
Func function1 = (action, data) -> {
new Thread(() -> {
System.out.println("Process-1");
try {
Thread.sleep(500);
} catch (InterruptedException e) {}
//Specify result value.(Any type can be specified)
action.resolve("Result-1");
}).start();
};
Func function2 = (action, data) -> {
System.out.println("Process-2 result=" + data);
action.resolve();
};
Promise.resolve()
.then(new Promise(function1))
.then(new Promise(function2))
.start();// start Promise operation
System.out.println("Hello,Promise");
}
}
Enter fullscreen mode Exit fullscreen mode
Result:
Hello,Promise
Process-1
Process-1 result=Result-1
Enter fullscreen mode Exit fullscreen mode
Tips
It’s also OK to just write Promise.then(func)
.
Promise.resolve()
.then(function1)
.then(function2)
.start();// start Promise operation
Enter fullscreen mode Exit fullscreen mode
Description
What is “Func” ?
Func is a java interface equivalent to JavaScript’s Function for argument of #then
public interface Func {
public void run(Action action, Object data) throws Exception;
}
Enter fullscreen mode Exit fullscreen mode
You can write Func like a JavaScript function.
I want to show two ways of implementing Func class.
No.1)Write Func object in the normal way.
Func function = new Func() {
@Override
public void run(Action action, Object data) throws Exception {
System.out.println("Process");//write your logic
action.resolve();
}
};
Enter fullscreen mode Exit fullscreen mode
No.2)Write Func object using lambda expression.
Func function = (action, data) -> {
System.out.println("Process");//write your logic
action.resolve();
};
Enter fullscreen mode Exit fullscreen mode
What is “Action” ?
Action object is an argument of Func#run method.
- Call action.resolve( [fulfillment value] ) to make the Promise’s status fulfilled and move on to the next processing(specified by then) with the result(fulfillment value).
action.resolve("Success");
Enter fullscreen mode Exit fullscreen mode
- Call action.reject( [rejection reason] ) to make the Promise’s status rejected and move on to the next processing(specified by then) with the result(rejection reason).
action.reject("Failure");
Enter fullscreen mode Exit fullscreen mode
- Argument is optional, you can call action.resolve() or action.reject()
action.resolve();//Argument can be omitted
Enter fullscreen mode Exit fullscreen mode
Usage
Rejection
If action.reject() is called, or if an exception thrown while executing Func.run(), rejected status is set to Promise, and the onRejected function specified to then is called.
- call
action.reject
Func function = (action, data) -> {
action.reject("Failure");
};
Enter fullscreen mode Exit fullscreen mode
- throw an exception
Func function = (action, data) -> {
throw new Exception("something");
};
Enter fullscreen mode Exit fullscreen mode
Let’s see Promise.then() method,
the 2nd argument of Promise.then() can be set to a Func to receive the result of rejection when receiving the result of then.
-
Syntax
Usage
Promise.then(onFulfilled[, onRejected]);
-
onFulfilled is a Func object called if the Promise is fulfilled.
You can receive the previous execution “fulfilled” result as an argument named data.
-
onRejected is a Func object called if the Promise is rejected.
You can receive the previous execution “rejected” result(mainly the objects are exceptions) as an argument named data.
//Rejection
public class ExampleRejection {
public static void main(String[] args) {
Promise.resolve()
.then((action, data) -> {
System.out.println("Process-1");
action.reject();
})
.then(
// call when resolved
(action, data) -> {
System.out.println("Resolved Process-2");
action.resolve();
},
// call when rejected
(action, data) -> {
System.out.println("Rejected Process-2");
action.resolve();
})
.start();// start Promise operation
System.out.println("Hello,Promise");
}
}
Enter fullscreen mode Exit fullscreen mode
Diagram:
Result:
Hello,Promise
Process-1
Rejected Process-2
Enter fullscreen mode Exit fullscreen mode
Promise.always
Promise.always() always receive both fulfilled and rejected results.
public class ExampleAlways {
public static void main(String[] args) {
Func func2OutReject = (action, data) -> {
action.reject("I send REJECT");
//action.resolve("I send RESOLVE");
};
Func func2ReceiveAlways = (action, data) -> {
System.out.println("Received:" + data);
action.resolve();
};
Promise.resolve()
.then(func2OutReject)
.always(func2ReceiveAlways)
.start();
}
}
Enter fullscreen mode Exit fullscreen mode
Result
Received:I send REJECT
Enter fullscreen mode Exit fullscreen mode
Promise.all
Execute multiple promises at the same time, and after all executions are complete, move to the next processing with then
- Execute multiple promises simultaneously and wait until all the execution is finished before proceeding.
- If all finishes with resolve, execution results will be stored as java.util.List in the order of invocation.
- If there is even one rejection, store that rejection reason in the result when the rejection occurs and move on to the next “then”.
import java.util.List;
import org.riversun.promise.Func;
import org.riversun.promise.Promise;
public class ExampleAll {
public static void main(String[] args) {
Func func1 = (action, data) -> {
Promise.sleep(1000);
System.out.println("func1 running");
action.resolve("func1-result");
};
Func func2 = (action, data) -> {
Promise.sleep(500);
System.out.println("func2 running");
action.resolve("func2-result");
};
Func func3 = (action, data) -> {
Promise.sleep(1500);
System.out.println("func3 running");
action.resolve("func3-result");
};
Func funcGetResult = (action, data) -> {
List<Object> resultList = (List<Object>) data;
for (int i = 0; i < resultList.size(); i++) {
Object o = resultList.get(i);
System.out.println("No." + (i + 1) + " result is " + o);
}
action.resolve();
};
Promise.all(func1, func2, func3)
.always(funcGetResult)
.start();
}
}
Enter fullscreen mode Exit fullscreen mode
Result:
func2 running
func1 running
func3 running
No.1 result is func1-result
No.2 result is func2-result
No.3 result is func3-result
Enter fullscreen mode Exit fullscreen mode
Threading
It is also possible to execute Promise processing on the specified executor.
Note if you use your own executor, remember to shut it down after use.
If you use your own executor, it will NOT be shutdown automatically
At least one worker thread to be used in Promise.all,
and one thread for overall asynchronous execution, so a total of two or more threads must be needed.
public class Example {
public static void main(String[] args) {
final ExecutorService myExecutor = Executors.newFixedThreadPool(5);
Func func1 = (action, data) -> {
System.out.println("func1 on " + Thread.currentThread().getName());
action.resolve();
};
Func func2 = (action, data) -> {
System.out.println("func2 on " + Thread.currentThread().getName());
action.resolve();
};
Func func3 = (action, data) -> {
System.out.println("func3 on " + Thread.currentThread().getName());
action.resolve();
};
Promise.all(myExecutor, func1, func2, func3)
.then((action, data) -> {
System.out.println("final process on " + Thread.currentThread().getName());
myExecutor.shutdown();//If you use your own executor, remember to shut it down after use
action.resolve();
})
.start();
}
}
Enter fullscreen mode Exit fullscreen mode
Result:
func1 on pool-1-thread-2
func2 on pool-1-thread-3
func3 on pool-1-thread-4
final process on pool-1-thread-1
Enter fullscreen mode Exit fullscreen mode
SyncPromise
SyncPromise, as the name implies, is a synchronous promise.
While Promise is executed asynchronously, SyncPromise does NOT move next while it is chained by “then”.
All other features are the same as Promise.
public class Example02 {
public static void main(String[] args) {
Func func1 = (action, data) -> {
new Thread(() -> {
System.out.println("Process-1");
action.resolve();
}).start();
};
Func func2 = (action, data) -> {
new Thread(() -> {
System.out.println("Process-2");
action.resolve();
}).start();
};
SyncPromise.resolve()
.then(func1)
.then(func2)
.start();
System.out.println("Hello,Promise");
}
}
Enter fullscreen mode Exit fullscreen mode
Result:
Process-1
Process-2
Hello,Promise
Enter fullscreen mode Exit fullscreen mode
Even if func1 and func2 are executed in a thread,
System.out.println("Hello,Promise")
is always executed after that.Because SyncPromise is synchronous execution.
暂无评论内容