All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.azbh111.utils.java.promise.Promise Maven / Gradle / Ivy

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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy