com.github.azbh111.utils.java.promise.Promise Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils-java Show documentation
Show all versions of utils-java Show documentation
com.github.azbh111:utils-java
The newest version!
package com.github.azbh111.utils.java.promise;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* @author pyz
* @date 2019/10/29 10:53 下午
*/
public class Promise {
private PromiseStatus status = PromiseStatus.PENDING;
private Object resolvedObject;
private Object rejectedObject;
private Object nextResolvedObject;
private Object nextRejectedObject;
private PromiseThen thennable;
private PromiseCatch catchable;
private PromiseFinally finnable;
private Promise next;
public synchronized void resolve(Object resolvedObject) {
if (status != PromiseStatus.PENDING) {
return;
}
status = PromiseStatus.RESOLVED;
this.resolvedObject = resolvedObject;
run();
}
public synchronized void reject(Object rejectedObject) {
if (status != PromiseStatus.PENDING) {
return;
}
status = PromiseStatus.REJECTED;
this.rejectedObject = rejectedObject;
run();
}
public void await() throws InterruptedException {
await(0);
}
public void await(long timeout) throws InterruptedException {
boolean keepWaiting = timeout == 0;
long leftWaitTimeNano = timeout * 1000000L;
while (true) {
if (status != PromiseStatus.PENDING) {
return;
}
if (!keepWaiting && leftWaitTimeNano <= 0) {
return;
}
synchronized (this) {
if (status != PromiseStatus.PENDING) {
return;
}
long start = System.nanoTime();
this.wait(leftWaitTimeNano / 1000000, (int) (leftWaitTimeNano % 1000000));
long end = System.nanoTime();
if (keepWaiting) {
continue;
}
leftWaitTimeNano -= (end - start);
}
}
}
private synchronized Promise then(PromiseThen thennable, PromiseCatch catchable, PromiseFinally finnable) {
this.thennable = thennable;
this.catchable = catchable;
this.finnable = finnable;
next = new Promise();
run();
return next;
}
private void handleNextResolve(Object resolvedObject, Promise promise) {
if (resolvedObject instanceof Promise) {
Promise p = (Promise) resolvedObject;
p.then(o -> {
promise.resolve(o);
return null;
}).catch_(e -> {
promise.reject(e);
return null;
});
} else {
promise.resolve(resolvedObject);
}
}
private void run() {
if (this.status == PromiseStatus.PENDING) {
return;
}
this.nextRejectedObject = null;
this.nextResolvedObject = null;
try {
if (status == PromiseStatus.RESOLVED) {
// then的返回值往下传递
if (this.thennable != null) {
this.nextResolvedObject = this.thennable.apply(this.resolvedObject);
} else {
this.nextResolvedObject = this.resolvedObject;
}
}
if (status == PromiseStatus.REJECTED) {
if (this.catchable != null) {
// 有catch的话, 把catch返回值往下resolve
this.nextResolvedObject = this.catchable.apply(this.rejectedObject);
} else {
// 没有catch的话,把rejectedObject往下reject
this.nextRejectedObject = this.rejectedObject;
}
}
if (this.finnable != null) {
this.finnable.run();
}
this.notifyAll();
} catch (Throwable e) {
// 报错了,往下reject
this.nextRejectedObject = e;
this.notifyAll();
if (next != null) {
next.reject(this.nextRejectedObject);
}
return;
}
if (next != null) {
if (status == PromiseStatus.REJECTED && this.catchable == null) {
next.reject(this.nextRejectedObject);
} else {
handleNextResolve(this.nextResolvedObject, next);
}
}
}
public Promise then(PromiseThen thennable) {
return then(thennable, null, null);
}
public Promise catch_(PromiseCatch catchable) {
return then(null, catchable, null);
}
public Promise finally_(PromiseFinally finnable) {
return then(null, null, finnable);
}
public T getResolvedObject() {
return (T) resolvedObject;
}
public T getRejectedObject() {
return (T) rejectedObject;
}
public PromiseStatus getStatus() {
return status;
}
public boolean isPending() {
return this.status == PromiseStatus.PENDING;
}
public boolean isResolved() {
return this.status == PromiseStatus.RESOLVED;
}
public boolean isRejected() {
return this.status == PromiseStatus.REJECTED;
}
public static Promise all(Promise... others) {
Promise promise = new Promise();
int size = others.length;
Object[] results = new Object[size];
AtomicInteger count = new AtomicInteger();
for (int i = 0; i < size; i++) {
int j = i;
others[i].then(res -> {
results[j] = res;
if (count.incrementAndGet() == size) {
promise.resolve(results);
}
return null;
}).catch_(e -> {
promise.reject(e);
return null;
});
}
return promise;
}
}