A lightweight implementation of the JavaScript Promise API in Java, using low-level concurrency primitives such as Thread, synchronized, and wait/notify.
- Core Promise Methods:
then(): Attach handlers for success and error states.catchError(): Handle rejections gracefully.andFinally(): Run cleanup logic after the Promise settles.
- Promise Combinators:
all(): Wait for all Promises to fulfill or reject on the first failure.race(): Resolve or reject as soon as one Promise settles.any(): Fulfill on the first successful Promise or reject if all fail.allSettled(): Wait for all Promises to settle, regardless of their outcome.
- Lightweight and Thread-Safe:
- Built using
synchronized,wait/notify, andThreadwithout relying onjava.util.concurrent. - Does not depend on external libraries.
- Built using
- Customizable:
- Add your own handlers and logic using functional interfaces.
- Java Development Kit (JDK) 8 or higher.
- Basic understanding of Java concurrency.
Clone the repository:
git clone https://github.com/evankost/promise-java.git
cd promise-javaAdd the project to your classpath or import it into your favorite IDE.
Promise<String> promise = new Promise<>((resolve, reject) -> {
new Thread(() -> {
try {
Thread.sleep(1000);
resolve.accept("Hello, World!");
} catch (Exception e) {
reject.accept(e);
}
}).start();
});
promise.then(value -> {
System.out.println("Resolved with: " + value);
return null;
}).catchError(error -> {
System.err.println("Rejected with: " + error.getMessage());
});Wait for all Promises to fulfill:
List<Promise<Integer>> promises = List.of(
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
);
Promise.all(promises).then(results -> {
System.out.println("All fulfilled: " + results);
return null;
});Resolve or reject as soon as one Promise settles:
Promise.race(List.of(
new Promise<>((resolve, reject) -> new Thread(() -> resolve.accept("Fast")).start()),
new Promise<>((resolve, reject) -> new Thread(() -> {
try { Thread.sleep(5000); resolve.accept("Slow"); } catch (Exception e) { reject.accept(e); }
}).start())
)).then(result -> {
System.out.println("Race winner: " + result);
return null;
});Fulfill on the first successful Promise or reject if all fail:
Promise.any(List.of(
Promise.reject(new RuntimeException("Failed 1")),
new Promise<>((resolve, reject) -> new Thread(() -> resolve.accept("Success")).start()),
Promise.reject(new RuntimeException("Failed 2"))
)).then(result -> {
System.out.println("First success: " + result);
return null;
}).catchError(error -> {
System.err.println("All failed: " + error.getMessage());
});Get the results of all Promises, regardless of their outcome:
Promise.allSettled(List.of(
Promise.resolve("A"),
Promise.reject(new RuntimeException("B failed")),
Promise.resolve("C")
)).then(results -> {
for (ValueOrError<?> result : results) {
if (result.hasError()) {
System.err.println("Rejected: " + result.error().getMessage());
} else {
System.out.println("Fulfilled: " + result.value());
}
}
return null;
});To ensure the functionality of the Promise implementation and build the project, you can use Gradle. Follow these steps:
-
Navigate to the project directory:
cd /path/to/your/project -
Build the Project: Use the following command to build the project and resolve dependencies:
./gradlew build
- This command compiles the source code, runs the tests, and packages the project.
- The build artifacts will be available in the
builddirectory.
-
Run Tests: To execute all the tests in the project:
./gradlew test- This will run all unit tests located in the
src/test/javadirectory. - Make sure you have written tests for your Promise implementation using a testing framework like JUnit.
- This will run all unit tests located in the
-
View Test Results:
- After running the tests, the results will be available in the
lib/build/reports/tests/test/index.htmlfile. - Open the file in a browser to view detailed reports of passed and failed tests.
- After running the tests, the results will be available in the
-
Clean and Rebuild: To ensure the project builds from a clean slate, use:
./gradlew clean build
- This command deletes previous build artifacts, recompiles the source code, and reruns the tests.
Academic use. Implementation of the (original repository) specification.