Code Monkey home page Code Monkey logo

jdeferred's Introduction

JDeferred 2.x

JDeferred is a Java Deferred/Promise library similar to JQuery's Deferred Object.

Inspired by JQuery and Android Deferred Object.

If you are using JDeferred 1.x, see JDeferred 1.x Documentation

Features

  • Deferred object and Promise
  • Promise callbacks
    • .then(…)
    • .filter(…)
    • .pipe(…)
    • .done(…)
    • .fail(…)
    • .progress(…)
    • .always(…)
    • .pipeAlways(…)
  • Multiple promises
    • .when(p1, p2, p3, …).then(…)
    • .race(p1, p2, p3, …).then(…)
    • .settle(p1, p2, p3, …).then(…)
  • Callable and Runnable wrappers
    • .when(new Runnable() {…})
    • .race(new Runnable() {…})
    • .settle(new Runnable() {…})
  • Uses Executor Service
  • Java Generics support
    • Deferred<Integer, Exception, Double> deferred;
    • deferred.resolve(10);
    • deferred.reject(new Exception());
    • deferred.notify(0.80);
  • Android Support
  • Java 8 Lambda friendly
  • Yes it's on Maven Central Repository!

Maven

<dependency>
    <groupId>org.jdeferred.v2</groupId>
    <artifactId>jdeferred-core</artifactId>
    <version>${version}</version>
</dependency>

Gradle

compile 'org.jdeferred.v2:jdeferred-core:${version}'

Find available versions on Maven Central Repository.

Compatibility

Compatibility reports between versions:

Quick Examples

Deferred object and Promise

Deferred deferred = new DeferredObject();
Promise promise = deferred.promise();
promise.done(new DoneCallback() {
  public void onDone(Object result) {
    ...
  }
}).fail(new FailCallback() {
  public void onFail(Object rejection) {
    ...
  }
}).progress(new ProgressCallback() {
  public void onProgress(Object progress) {
    ...
  }
}).always(new AlwaysCallback() {
  public void onAlways(State state, Object result, Object rejection) {
    ...
  }
});

With the reference to deferred object, you can then trigger actions/updates:

deferred.resolve("done");
deferred.reject("oops");
deferred.notify("100%");

Filter

Use .filter(...) instead of .then(...) since 2.0.0-Beta2

Deferred d = …;
Promise p = d.promise();
Promise filtered = p.filter(new DoneFilter<Integer, Integer>() {
  public Integer filterDone(Integer result)
    return result * 10;
  }
});

filtered.done(new DoneCallback<Integer>() {
  public void onDone(Integer result) {
    // result would be original * 10
    System.out.println(result);
  }
});

d.resolve(3) -> 30.

Pipe

Use .pipe(...) instead of .then(...) since 2.0.0-Beta2

Deferred d = ...;
Promise p = d.promise();

p.pipe(new DonePipe<Integer, Integer, Exception, Void>() {
  public Deferred<Integer, Exception, Void> pipeDone(Integer result) {
    if (result < 100) {
      return new DeferredObject<Integer, Void, Void>().resolve(result);
    } else {
      return new DeferredObject<Integer, Void, Void>().reject(new Exception(...));
    }
  }
}).done(...).fail(...);

d.resolve(80) -> done!
d.resolve(100) -> fail!

Deferred Manager

DeferredManager dm = new DefaultDeferredManager();
Promise p1, p2, p3;
// initialize p1, p2, p3
dm.when(p1, p2, p3)
  .done(…)
  .fail(…)

You can also specify a Executor Service for your need.

DeferredManager dm = new DefaultDeferredManager(myExecutorService);

Runnable and Callable

You can use Callable and Runnable almost like a Promise without any additional work.

DeferredManager dm = new DefaultDeferredManager();
dm.when(new Callable<Integer>(){
  public Integer call() {
    // return something
    // or throw a new exception
  }
}).done(new DoneCallback<Integer>() {
  public void onDone(Integer result) {
    ...
  }
}).fail(new FailCallback<Throwable>() {
  public void onFail(Throwable e) {
    ...
  }
});

If you need to notify progress within your Callable or Runnable, you either need to create your own Deferred object and Promise, or you can use DeferredCallable and DeferredRunnable.

Use your own Deferred object

final Deferred deferred = ...
Promise promise = deferred.promise();
promise.then(…);
Runnable r = new Runnable() {
  public void run() {
    while (…) {
      deferred.notify(myProgress);
    }
    deferred.resolve("done");
  }
}

Or, extending DeferredRunnable

DeferredManager dm = …;
dm.when(new DeferredRunnable<Double>(){
  public void run() {
    while (…) {
      notify(myProgress);
    }
  }
}).then(…);

Wait and WaitSafely

Since 1.0.1

Normally, when using this framework, you would want to do things asynchronously. However, if there is a need to wait for all deferred tasks to finish, you can use Object.wait or Promise.waitSafely methods.

Promise p = dm.when(...)
  .done(...)
  .fail(...)

synchronized (p)
  while (p.isPending()) {
    try {
      p.wait();
    } catch (InterruptedException e) { ... }
  }
}

Alternatively, you can use a more simplified shortcut

Promise p = dm.when(...)
  .done(...)
  .fail(...)

try {
  p.waitSafely();
} catch (InterruptedException e) {
  ... 
}

Java 8 Lambda

Now this is pretty cool when used with Java 8 Lambda!

dm.when(() -> {
  return "Hey!";
}).done(r -> System.out.println(r));

dm.when(
  () -> { return "Hello"; },
  () -> { return "World"; }
).done(rs ->
  rs.forEach(r -> System.out.println(r.getResult()))
);

When

Calls to when with multiple arguments results in a Promise that signals fail on the first rejection or signals done with all computed values.

Success scenario

Callable<Integer> c1 = () -> 1;
Callable<Integer> c2 = () -> 2;
Callable<Integer> c3 = () -> 3;
Promise<MultipleResults3<Integer, Integer, Integer>, OneReject<Throwable>, MasterProgress> p = dm.when(c1, c2, c3);
p.done(MultipleResults3<Integer, Integer, Integer> r -> {
  Assert.assertEquals(r.getFirst(), 1);
  Assert.assertEquals(r.getSecond(), 2);
  Assert.assertEquals(r.getThird(), 3);
});

Failure scenario

Callable<Integer> c1 = () -> 1;
Callable<Integer> c2 = () -> 2;
Callable<Integer> c3 = () -> throw new RuntimeException("boom!");
Promise<MultipleResults3<Integer, Integer, Integer>, OneReject<Throwable>, MasterProgress> p = dm.when(c1, c2, c3);
p.done(MultipleResults3<Integer, Integer, Integer> r -> Assert.fail("should not be called"))
 .fail(OneReject<Throwable> r -> Assert.assertEquals(r.getReject().getMessage(), "boom!"));

Since 2.0.0

Calls to when with multiple arguments (up to five) will produce results with typesafe getters.

Race

Since 2.0.0

Calls to race with multiple arguments results in a Promise that signals fail on the first rejection or signals done on the first resolution.

Success scenario

Callable<Integer> c1 = () -> { Thread.sleep(200); return 1; };
Callable<Integer> c2 = () -> { Thread.sleep(100); return 2; };
Callable<Integer> c3 = () -> { Thread.sleep(200); return 3; };
Promise<OneResult<?>, OneReject<Throwable>, Void> p = dm.race(c1, c2, c3);
p.done(OneResult<?> r -> Assert.assertEquals(r.getResult(), 2));

Failure scenario

Callable<Integer> c1 = () -> { Thread.sleep(200); return 1; };
Callable<Integer> c2 = () -> { Thread.sleep(100); throw new RuntimeException("boom!"); };
Callable<Integer> c3 = () -> { Thread.sleep(200); return 3; };
Promise<OneResult<?>, OneReject<Throwable>, Void> p = dm.race(c1, c2, c3);
p.done(OneResult<?> r -> Assert.fail("should not be called")
  .fail(OneReject<Throwable> r -> Assert.assertEquals(r.getReject().getMessage(), "boom!"));

Settle

Since 2.0.0

Calls to settle with multiple arguments results in a Promise that collects all resolutions and rejections.

Callable<Integer> c1 = () -> { Thread.sleep(200); return 1; };
Callable<Integer> c2 = () -> { Thread.sleep(100); throw new RuntimeException("boom!"); };
Callable<Integer> c3 = () -> { Thread.sleep(200); return 3; };
Promise<AllValues, Throwable, MasterProgress>, Void> p = dm.race(c1, c2, c3);
p.done(AllValues r -> {
  Assert.assertEquals(r.get(0).getValue(), 1);
  Assert.assertTrue(r.get(1).getValue() instanceof RuntimeException);
  Assert.assertEquals(r.get(2).getValue(), 3);
});

Cancellation Handler

Since 2.0.0

Sometimes a task may be cancelled while its running and would require ti cleanup any resources it may have allocated. You may define a task that implements the org.jdeferred2.CancellationHandler interface or pass and extra argument to DeferredFutureTask with such implementation, for example

final DataSource datasource = ...;
class DatabaseTask extends Runnable, CancellationHandler {
  @Override
  public void run() {
    // perform computation with datasource
  }

  @Override
  public void onCancel() {
    try {
      datasource.close();
    } catch(Exception e) {
      throw new IllegalStateException(e);
    }
  }
}

DeferredFutureTask<X> task = new DeferredFutureTask(new DatabaseTask());
dm.when(task).done(...)

You may also pass the CancellationHandler as an additional argument, for example

final DataSource datasource = ...;
class DatabaseTask extends Runnable {
  @Override
  public void run() {
    // perform computation with datasource
  }
}

class DatabaseCancellationHandler implements CancellationHandler {
  @Override
  public void onCancel() {
    try {
      datasource.close();
    } catch(Exception e) {
      throw new IllegalStateException(e);
    }
  }
}

DeferredFutureTask<X> task = new DeferredFutureTask(new DatabaseTask(), new DatabaseCancellationHandler());
dm.when(task).done(...)

Groovy

You can also easily use with Groovy!

@Grab('org.jdeferred.v2:jdeferred-core:2.0.0')
import org.jdeferred2.*
import org.jdeferred2.impl.*

def deferred = new DeferredObject()
def promise = deferred.promise()

promise.done { result ->
  println "done: $result" 
}.fail { rejection ->
  println "fail: $rejection"
}.always { state, result, rejection ->
  println "always"
}

deferred.resolve("done")

Android Support

Since 1.1.0-Beta1

jdeferred-android is now available, and it can be included just like any other Android libraries! It also uses Android Maven plugin and builds apklib file. If you use Android Maven plugin, you can include dependency:

APKLIB with Maven:

<dependency>
  <groupId>org.jdeferred.v2</groupId>
  <artifactId>jdeferred-android</artifactId>
  <version>${version}</version>
  <type>apklib</type>
</dependency>

AAR with Maven:

Since 1.2.0-Beta1

<dependency>
  <groupId>org.jdeferred.v2</groupId>
  <artifactId>jdeferred-android-aar</artifactId>
  <version>${version}</version>
  <type>aar</type>
</dependency>

AAR with Gradle:

compile 'org.jdeferred.v2:jdeferred-android-aar:${version}'
// or
compile 'org.jdeferred.v2:jdeferred-android-aar:${version}@aar'

Find available versions on Maven Central Repository.

jdeferred-android introduces a new DeferredManager implementation called AndroidDeferredManager. AndroidDeferredManager makes sure that callbacks are executed in UI Thread rather than background Thread in order for callbacks to make UI updates. Alternatively, callbacks can also implement AndroidExecutionScopeable interface to fine-grain control whether the callback should execute in UI Thread or background Thread.

AndroidDeferredManager also supports new DeferredAsyncTask object. This object is based on Android's AsyncTask.

If you need to always execute callbacks in background thread, then you can continue to use DefaultDeferredManager.

Lastly, because JDeferred use SLF4J - you can further route log messages using slf4j-android.

Asynchronous Servlet

Here is a sample code on how to use JDeferred with Asynchronous Servlet!

@WebServlet(value = "/AsyncServlet", asyncSupported = true)
public class AsyncServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  private ExecutorService executorService = Executors.newCachedThreadPool();
  private DeferredManager dm = new DefaultDeferredManager(executorService);

  protected void doGet(HttpServletRequest request,
                       HttpServletResponse response) throws ServletException, IOException {
    final AsyncContext actx = request.startAsync(request, response);
    
    dm.when(new Callable<String>() {
      @Override
      public String call() throws Exception {
        if (actx.getRequest().getParameter("fail") != null) {
          throw new Exception("oops!");
        }
        Thread.sleep(2000);
        return "Hello World!";
      }
    }).then(new DoneCallback<String>() {
      @Override
      public void onDone(String result) {
        actx.getRequest().setAttribute("message", result);
        actx.dispatch("/hello.jsp");
      }
    }).fail(new FailCallback<Throwable>() {
      @Override
      public void onFail(Throwable exception) {
        actx.getRequest().setAttribute("exception", exception);
        actx.dispatch("/error.jsp");
      }
    });
  }
}
<script type="text/javascript"> /* */ </script> <script type="text/javascript" src="//www.googleadservices.com/pagead/conversion.js"> </script>

Deprecations

v1.2.5

  • DeferredManager.StartPolicy.MANAUL is deprecated and will be removed in the next minor version. Use DeferredManager.StartPolicy.MANUAL instead.

jdeferred's People

Contributors

aalmiray avatar abdelrahmaneb avatar aradchykov avatar aveuiller avatar bearprada avatar culmat avatar danielfaust avatar dgelvin avatar funnythingz avatar jonathanhds avatar mrmaffen avatar qmwu2000 avatar saturnism avatar sclassen avatar sis-yoshiday avatar supergillis avatar tigrawap avatar uhees avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jdeferred's Issues

Usage with network calls, errors swallowed

Trying to have network calls run with jdeferred, but responses never seem to return and errors are swallowed. Is there a better way to do the below? This is in an Android lib module, being tested on a junit module. Side note: the lambdas work on Android using Retrolambda

Below uses org.apache.http (had an initial working version with futures from Async-Http-Client, but Android said it was making network calls on the main thread)

private static final  Promise __getRequest(String url) {
       Deferred d = new DeferredObject();
        Promise p = d.promise();
        //AndroidDeferredManager adm = new AndroidDeferredManager();
        DeferredManager dm = new DefaultDeferredManager();

        final HttpParams httpParameters = new BasicHttpParams(); // Have also tried putting these in the lambda
        final HttpClient client = new DefaultHttpClient(httpParameters);
        final HttpGet method = new HttpGet(url); // url string

        dm.when(() -> {
            try {
                HttpResponse response = client.execute(method); // *** Gets here, then dies on step-over, no error thrown, nothing.

                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                return result;
            } catch (Exception e) {
                return "frick"; // Never gets here
            }
        }).done(result -> {
            // Do stuff (never gets here)
            // has d.resolve(<stuff>)
        }).fail(error -> {
            // Never gets here either
            // has d.reject(error)
        });

        return p;
    }

Appreciate the help.
PS Should I be posting this on SO instead of here?

How to chain several promises?

Using javascript promise libraries like "bluebird" i can return another promise inside "then" and call "then" again with the result of the last promise.

SocialAccount.forge({user_id: user.id, network: network}).fetch({require: true}).then(function(socialAccount) {
  return socialAccount.save({show_link: show === true ? 1 : 0}, {patch: true}); // Returns a new promise
}).then(function(socialAccount) {
  resolve(socialAccount);
}).catch(NotFoundError, function(err) {
  reject(messages.notFoundError('user.showNetwork.userNotConnected', 'The user is not connected to this network', err));
}).catch(function(err) {
  reject(messages.unexpectedError('user.showNetwork.error', 'Error setting network to show user link.', err));
});

It is possible to reproduce this example using JDeferred?
Thanks!

ProgressPipe doesn't work

First, thanks for good work on this library.

I believe there's a problem on ProgressPipe.

deferred.then(null, null, new ProgressPipe<Double, Result, Exception, String> {
pipeProgress(Double percent) {
DeferredObject<Result, Exception, String> d = new ...
d.notify(percent * 100 + "%");
return d;
}
}).progress(new ProgressCallback() {
onProgress(String progress) {
// this will never get called.
}
}
deferred.notify(0.5);

I believe the reason is "ProgressCallback will not be called if we add it AFTER notify", I believe this is designed behavior. Like following:

deferred.notify(0.5);
deferred.progress(new ProgressCallback() {
void onProgress(Double progress) {
// this will never get called.
}
}

Fork for a GWT open-source project

Hi Ray. I've forked the core part of your project to Turbo GWT (Core). I'll use it in the HTTP module, and I had to make a slight change on the AlwaysCalback (instead of just the State, I need a Context with more information). I've kept all the license/credits in the classes and in the main page of the Core project. Turbo GWT is under Apache2 license too. Thanks for your excellent work.

Is AndroidDeferredManager always return MultipleResults in the same order?

I just need confirmation, from the following snippets:

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        AndroidDeferredManager androidDeferredManager = new AndroidDeferredManager();
        androidDeferredManager
                .when(new Callable<Object>() {
                            @Override
                            public String call() throws Exception {
                                Thread.sleep(3000);
                                return "Hello World 1!";
                            }
                        },
                        new Callable<Object>() {
                            @Override
                            public String call() throws Exception {
                                Thread.sleep(2000);
                                return "Hello World 2!";
                            }
                        },
                        new Callable<Object>() {
                            @Override
                            public String call() throws Exception {
                                Thread.sleep(1000);
                                return "Hello World 3!";
                            }
                        },
                        new Callable<Object>() {
                            @Override
                            public String call() throws Exception {
                                Thread.sleep(1900);
                                return "Hello World 4!";
                            }
                        })
        .done(new DoneCallback<MultipleResults>() {
            @Override
            public void onDone(MultipleResults result) {
                for(OneResult res: result){
                    Log.d("LOG", "Result: " + res.toString());
                }
            }
        });
    }
});

I saw the following logs:

08-11 11:21:57.853    6234-6234/id.flwi.deferredtesting D/LOG﹕ Result: OneResult [index=0, promise=org.jdeferred.android.AndroidDeferredObject@533e7b78, result=Hello World 1!]
08-11 11:21:57.853    6234-6234/id.flwi.deferredtesting D/LOG﹕ Result: OneResult [index=1, promise=org.jdeferred.android.AndroidDeferredObject@533e990c, result=Hello World 2!]
08-11 11:21:57.853    6234-6234/id.flwi.deferredtesting D/LOG﹕ Result: OneResult [index=2, promise=org.jdeferred.android.AndroidDeferredObject@533e9a94, result=Hello World 3!]
08-11 11:21:57.853    6234-6234/id.flwi.deferredtesting D/LOG﹕ Result: OneResult [index=3, promise=org.jdeferred.android.AndroidDeferredObject@533e9c28, result=Hello World 4!]

Result is always in that order. So again, Is MultipleResults always came in the same order?

AndroidDeferredObject running callbacks in background thread

In Android I want to be able to run callbacks in background thread when resolve called from UI thread and AndroidExecutionScope.BACKGROUND passed in constructor. For example if i run this code in UI thread:

DeferredObject deferred = new DeferredObject();
AndroidDeferredObject androidDeffered = new
AndroidDeferredObject(deferred,AndroidExecutionScope.BACKGROUND);

androidDeffered.then(new DoneCallback(){
// currently run in UI thread, suppose to be running in background thread
});

androidDeffered.resolve("Done");

I don't want to use AndroidDefferedManager, since i want to return to my application Promise without done method and trigger it via resolve function.

Running promises on specific threads

Hi

I was looking to start using promises to remove the callback hell I've accumulated in my application, but I need to be able to ensure that a promise is run in a specific thread pool.

I had thought that DefaultDeferredManager.when(Promise) would do just that, but in fact it does nothing.

I was thinking you'd need something like this:

   private static <D, F, P> Promise<D, F, P> schedule(Promise<D, F, P> promise, Executor exe)
   {
      ScheduledDeferredObject<D, F, P> mdo = new ScheduledDeferredObject<>(exe);
      promise.then((D d) -> mdo.resolve(d), (F f) -> mdo.reject(f), (P p) -> mdo.notify(p));
      return mdo;
   }

   private static class ScheduledDeferredObject<D, F, P> extends DeferredObject<D, F, P>
   {
      private final Executor executor;

      public ScheduledDeferredObject(Executor executor)
      {
         this.executor = executor;
      }

      @Override
      public Deferred<D, F, P> resolve(final D resolve)
      {
         executor.execute(() -> super.resolve(resolve));
         return this;
      }

      @Override
      public Deferred<D, F, P> reject(final F reject)
      {
         executor.execute(() -> super.reject(reject));
         return this;
      }

      @Override
      public Deferred<D, F, P> notify(final P progress)
      {
         executor.execute(() -> super.notify(progress));
         return this;
      }
   }

Regards
Stephen

Add Uncaught Exception Handler

In DeferredManager, add ability to register a catch all uncaught exception handler. In case any Throwable was uncaught, pass it to the handler.

Applications should always try to handle known exceptions in the fail() handler explicitly. This is as a last-resort fallback.

By default, the handler will log the uncaught exception.

Passing non-void parameters to the DeferredAsyncTask

I've been trying to replace the

new DeferredAsyncTask<Void, Throwable, Object>

with a

class DeferredFlowControl {
    String mURL = "...";
    String mDownloadResult = null;
    String mFilename = "...";
    String mSaveResult = null;
}
final DeferredFlowControl dfcSequence = new DeferredFlowControl();

new DeferredAsyncTask<DeferredFlowControl, Throwable, Object>

but I can't find a way to make use of that DeferredFlowControl instance named dfcSequence.

I could make the tasks read/write the variables of the dfcSequence directly, but I'm trying to pass that dfcSecuence around as a parameter, as I can do with normal AsyncTasks, by passing it to the AsyncTask.execute(dfcSequence);

Is it possible to do this? The DeferredAsyncTask never gets to call the doInBackgroundSafe, as a java.lang.ClassCastException: java.lang.Void[] cannot be cast to .....$1DeferredFlowControl exception is raised.

jdeferred-parent in MavenCentral is out of date

I'm trying to include jdeferred-core into an android app using gradle like so:

dependencies {
    compile 'org.jdeferred:jdeferred-core:1.0.0'
}

I get an error when doing ./gradlew clean build:

* What went wrong:
A problem occurred configuring project ':MyApp'.
> Failed to notify project evaluation listener.
   > Could not resolve all dependencies for configuration ':MyApp:_DebugCompile'.
      > Could not resolve org.jdeferred:jdeferred-core:1.0.1.
        Required by:
            MyApp:MyApp:unspecified
         > Could not find any version that matches org.jdeferred:jdeferred-parent:1.0.1.

I checked out Maven central, and though it appears that jdeferred and jdeferred-core have v1.0.1s, jdeferred-parent is v1.0.0, which I believe is causing there error.

I worked around it by just using jdeferred-core:1.0.0 but I thought I'd bring it up.

Cancel functionality

Cancel functionality is missing:
Missing State.CANCELED with cancel() method and onCancel listener. If promise is in pending state and cancel method was called, move the state to CANCELED, call onCancel method.

How to create rejected promise?

Hello. Thanks for the project.
So, a little question - how I can create rejected promise? For example:

Promise downloadFile(String url, String localPath) {
        try {
            return downloadFile(new URL(url), localPath);
        } catch (MalformedURLException e) {
            return ????; // I want to return simple rejected Promise, in one line. How?
        }
}
Promise downloadFile(URL url, String localPath) {
        /// ... DeferredAsyncTask, etc
}

Thanks in advice

Readme issue

In the Filter section, you use a P instead of a {.

public Integer filterDone(Integer result) P
return result * 10;
}

vertx support

Provide support for vert.x so that the same paradigm/interfaces can work seamlessly in vert.x

wait(timeout)

Any chance of getting a Promise.wait(timeout) function added? This would be a nice addition when the need arises to block while several promises are completing in a DeferredManager. While, you would say that you continue the async tasks in a dm.then() handler, there are some situations with some web frameworks where blocking to continue in a synchronous manner are helpful.

DeferredCallable has different type parameters than Promise/Deferred

DeferredCallable has type parameters <D, P> while Promises have type parameters <D, F, P> . That means the Deferred in the DeferredCallable has error type "Throwable" instead of a user specified error type.

I'd like to specify my own error type with DeferredCallable. Was this difference intended or is it a TBD? Is there any reason not to add a type parameter for errors in DeferredCallable?

Source files without license headers

Hi
The following source files are without license headers:
./android/test/src/main/java/org/jdeferred/android/test/AndroidDeferredManagerTest.java
./android/test/src/main/java/org/jdeferred/android/test/MainActivity.java

./core/src/main/java/org/jdeferred/DeferredRunnable.java
./core/src/main/java/org/jdeferred/DeferredCallable.java

Please, confirm the licensing of code and/or content/s, and add license headers
https://fedoraproject.org/wiki/Packaging:LicensingGuidelines?rd=Packaging/LicensingGuidelines#License_Clarification

Thanks in advance
Regards

AndroidDeferredManager javadoc typo

On line 137, you say:

If this a non-Android friendly promise is passed in, wrap it with {@link AndroidDeferredObject} so that callbacks can be executed in UI thread.

I think you meant to say

If this is ...

and

... be executed in the UI thread.

Catching and logging exceptions causes program to not notice.

Hey, when using JDeferred along with a netty-based program, I created a NullPointerException. Unfortunately, the promise i had was never rejected because the deferred object threw a null pointer exception. Here's an example:

final String str = null;
deferred.then( () -> otherPromise.resolve(null.size()) );

That nullpointerexception will just be eaten and never keyed off of. The only option i see is to wrap everything in these try {} catch(Exception e){} blocks, but i'd rather be able to have an "except" tag or something to deal with caught exceptions ( for example)

final String str = null;
deferred.then( () -> otherPromise.resolve(null.size()) )
    .except((e) -> otherpromise.reject());

Support for a whenAny method

Would it be possible to support a whenAny method where you can have several Callables that as soon as one is successfully returned, the DoneCallback with the result is called with the result (and canceling/failing all remaining Callables if they can be canceled)?

Here's a unit test for the use case:

@Test(timeout = 3000)
public void testWhenAny() {
    final AtomicInteger doneCount = new AtomicInteger();
    final AtomicInteger failCount = new AtomicInteger();
    final AtomicBoolean callable1Run = new AtomicBoolean(false);
    final AtomicBoolean callable2Run = new AtomicBoolean(false);
    final AtomicBoolean callable3Run = new AtomicBoolean(false);

    Promise<OneResult, OneReject, MasterProgress> p = deferredManager.whenAny(new Callable<Integer>() {
        public Integer call() {
            try {
                Thread.sleep(2000);
                callable1Run.set(true);
            } catch (InterruptedException e) {
            }

            return 100;
        }
    }, new Callable<Integer>() {
        public Integer call() {
            try {
                Thread.sleep(500);
                callable2Run.set(true);
            } catch (InterruptedException e) {
            }

            throw new RuntimeException("Oops");
        }
    }, new Callable<String>() {
        public String call() {
            try {
                Thread.sleep(5000);
                callable3Run.set(true);
            } catch (InterruptedException e) {
            }

            return "Hello";
        }
    }).then(new DoneCallback<OneResult>() {
        public void onDone(OneResult result) {
            Assert.assertEquals(100, result.getResult());
            doneCount.incrementAndGet();
        }
    }).fail(new FailCallback<OneReject>() {
        public void onFail(OneReject result) {
            if (failCount.incrementAndGet() == 1) {
                Assert.assertEquals(RuntimeException.class, result.getReject().getClass());
                RuntimeException e = (RuntimeException) result.getReject();
                Assert.assertEquals("Oops", e.getMessage());
            }
        }
    });

    Assert.assertTrue(callable1Run.get());
    Assert.assertTrue(callable2Run.get());
    Assert.assertFalse(callable3Run.get());
    Assert.assertEquals(1, doneCount.get());
    Assert.assertEquals(2, failCount.get());
}

1.2.4 release to maven central?

Hi, is there a plan to release v1.2.4 to maven central?
I am interested in particular in the memory leak fix that was merged in 2ea5d9. I can pull the source myself, but it would be great to be able to pull in the jar the usual way via my pom file, etc.

Thanks!

Promise.then(DoneCallback) does not fail if onDone fails

As a consequence of issue #7 piping seems a little bit broken (according to the jQuery standards again) on Promise.then(DoneCallback). The JavaDoc clearly says that this is equivalent to promise.done but according to piping it should fail if the DoneCallback fails.

This is again may be by design and if you feel this is wrong just close the issue.

Make a way to shove extra logging information into the MDC for promises as they resolve

Logging frameworks have a thing called an MDC. It's a way to store extra metadata that then gets logged with every message in that thread. They use ThreadLocal to implement this. With this move to promises, the thread a request is running on is not often the same one that initiated it.

I propose we add a boolean optional function call on promises, with a static global setter as well, that says to "preserveIssuerMdc" on promise resolutions.

If this is true, we build out the resolving thread's mdc to match the issuer's mdc exactly before calling promise callbacks.

The issuer is determined to be the caller of done(), fail(), progress(), then(). Every instantiation of this would store a reference to the parent mdc.

If anyone's interested, i'd be happy to make a fork to do this change. It might be somewhat expansive.

Returning a promise from a filter and add callbacks to that promise

This is based on #7 submitted by @mehiel, and his jquery example: http://jsfiddle.net/Bh8TA/1/

from @mehiel

Example 1: Throwing an excpetion on then's callback.
Outcome: @paolito is right. My assumption about exceptions was wrong, it is true that jQuery does not reject on uncaught exceptions. So jDeferred works as intended for this one.

Example 2: Filtering a value that came out of a promise.
Outcome: jDeferred also works as intended.

Example 3: Returning a promise from a DoneFilter and add callbacks to that promise.
Outcome: is jDeffered able to handle this situation? I think we're missing that. @paolito this is what you mentioned, isn't it?

from @paolito

What's missing in @jdeferred and would be extremely useful (see the last example at http://api.jquery.com/deferred.then/) is possibility for filters to return promise and have @jdeferred automatically rewire callbacks registred to promise created by then() to promise that will be returned from callback, when it is executed

Notify progress

How do I notify the progress from a Deferred object? I have the following code:

    Deferred<String, Exception, String> d = new DeferredObject<>();
    Promise<String, Exception, String> p = d.promise();
    new Thread(() -> {
        for (String name : names) {
            String expensiveOperationStepOutput = reallyExpensiveFunction(name)
            d.notify("Actual notification");
            System.out.println("Notified");
        }
        d.resolve("done");
    }).run();
    return p;

And then somewhere I do:

    Promise<String, Exception, String> p = sm.fetchExpensiveThings();
    p.then(result -> {
        System.out.println("Done!");
    });
    p.progress(progress -> System.out.println("Called!"));

But when I run the above code, I see a lot of "Notified" and a "Done" at the end, but never "Called". How do I do this?

Support for array of Callables/Promises on then (Promise.all)

If we need to assure execution of all callables before calling the next in line, in a pipe, we have to do this:

final List<Callable<String>> callables = ImmutableList.of(callable1, callable2);

dm.when(doCall1)
  .then(new DonePipe<String, MultipleResults, OneReject, MasterProgress>() {
                    @Override
                    public Promise<MultipleResults, OneReject, MasterProgress> pipeDone(String result) {
                        return dm.when(callables.toArray(new Callable[callables.size()]));
                    }
                })
  .then(new DoneCallback<MultipleResults>() {
                    @Override
                    public void onDone(MultipleResults result) {
                        System.out.println("Now all the callables have finished");
                    }
                });

Instead, we should be able to do something like:

final List<Callable<String>> callables = ImmutableList.of(callable1, callable2);

dm.when(doCall1)
  .then(Promise.all(callables))
  .then(new DoneCallback<List<String>>() {
                    @Override
                    public void onDone(List<String> result) {
                        System.out.println("Now all the callables have finished");
                    }
                });

waitSafely - why does this work?

I opened a question on StackOverflow and have found a solution, but I don't fully understand why it works. The solution appears related to jdeferred, so I thought you might be able to shed light on it.

I am using waitSafely to test code that is run in a thread. My broken code looked like this:

    Promise prom = client.find(new VideoQueue())
            .set("user", "212139")
            .run()
            .done(new DoneCallback<ArrayList<VideoQueue>>() {
                @Override
                public void onDone(ArrayList<VideoQueue>  videoQueue) {
                    assertNotNull(videoQueue);
                    assertNotNull(videoQueue.get(0));
                    assertNotNull(videoQueue.get(0).getId());
                    assertEquals("3310190", videoQueue.get(0).getId());
                }
            }).fail(new FailCallback() {
                @Override
                public void onFail(Object rejection) {
                    assertNull(rejection);
                }
            });

    prom.waitSafely();

The result was that the test runner would fully exit when an assertion failed. After moving waitSafely before done, the issue has resolved itself. The assertion fails, but the runner continues through the other tests. The code below works.

        Promise prom = client.find(new VideoQueue())
                .set("user", "212139")
                .run();

        prom.waitSafely();

        prom.done(new DoneCallback<ArrayList<VideoQueue>>() {
                    @Override
                    public void onDone(ArrayList<VideoQueue>  videoQueue) {
                        assertNotNull(videoQueue);
                        assertNotNull(videoQueue.get(0));
                        assertNotNull(videoQueue.get(0).getId());
                        assertEquals("3310190", videoQueue.get(0).getId());
                    }
                }).fail(new FailCallback() {
                    @Override
                    public void onFail(Object rejection) {
                        fail();
                    }
                });

Do you have any insight into why this change works?

AndroidExecutionScope doesn't work

I'm trying to get certain callbacks to run in the background by using AndroidDeferredManager and Android****Callback functions that return AndroidExecutionScope.BACKGROUND in getExecutionScope(), but no matter what the callbacks always seem to execute on the main UI thread.

This is the test I'm using to see which thread the callback is executing on:

  if (Looper.myLooper() == Looper.getMainLooper()) {
    Log.e(TAG, "bg thread on main"); 
  } else {
     Log.d(TAG, "bg thread on bg");
  }

Even using DefaultDeferredManager, the callbacks run in the main UI thread. The only thing that does work is the DeferredAsyncTask passed to the AndroidDeferredManager, but I would like to be able to use the callbacks.

If this is not a bug, please provide more documentation/examples on how to use these callbacks on Android.

waitSafely does not work as expected

So, I have a small DeferredAsyncTask

public DeferredAsyncTask<Void, Integer, WebCall> getRequestTask(WebCall webcall) {
        return new DeferredAsyncTask<Void, Integer, WebCall>() {
            @Override
            protected WebCall doInBackgroundSafe(Void... voids) throws Exception {
                 //do stuff
                return webcall;
            }
        };
    }

that is called in a small flow

try {
    DeferredAsyncTask<Void, Integer, WebCall> requestTask = http.getRequestTask(webCall);
    new AndroidDeferredManager().when(requestTask).done(new DoneCallback<WebCall>() {
        @Override
        public void onDone(WebCall result) {
            value.set(result.getResponsePayload());
            Log.i(Constants.LOG_TAG, "webcall - result " + result.getResponsePayload());
        }
    }).fail(new FailCallback<Throwable>() {
        @Override
        public void onFail(final Throwable tr) {
            Log.i(Constants.LOG_TAG, "webcall - " + tr.getMessage());
        }
    }).waitSafely();
} catch (Exception e) {
    e.printStackTrace();
}

When using waitSafely() it just hangs. Nothing is written to the logcat, program execution is halted. Implementation seem to be fine according to the documentation. Any ideas?

FilteredPromise does not fail if filterDone fails

I was trying to do a piped promise and I found out that on .then(DoneFilter) if the code on filterDone method fails with an exception the FilteredPromise does not fail

This happens bacause at FilteredPromise:41 we don't catch any exceptions happened in filterDone. This may be by design but it is not what jQuery does, is it? Feels different.

Chained pipes in sequential order

Hi,
I'm trying to chain multiple pipes.

I'm facing the issue that the second pipe, which the code in block 3, is running in parallel with the block 2.

I know that I apparently would need to pipe the code in block 3 to the promise p2, but that doesn't feel right. Wouldn't it make more sense for p2 to replace p during the DonePipe?

How can I archive what I want, without nesting block 3 into the DonePipe.pipeDone of block 2? This means, how can I access p3 from outside of the wrapper it's running in, that is, at the same level as the promise p?

Could I pre-build the promises without making them execute, and then execute them later when required?

Thanks in advance.

final AndroidDeferredManager dm = new AndroidDeferredManager();

// block 1
Promise p = dm.when(new DeferredAsyncTask<Void, Integer, Object>() {
    @Override protected String doInBackgroundSafe(Void... nil) throws Exception {
        Log.v(TAG, "+++++++ BACKGROUND SLEEP");
        Thread.sleep(6000);
        Log.v(TAG, "+++++++ BACKGROUND RESUME");
        return "done";
    }
}).always(new AlwaysCallback<Object, Throwable>() {
    @Override
    public void onAlways(Promise.State state, Object o, Throwable throwable) {
        Log.v(TAG, "+++++++ ALWAYS " + state.toString() + " o: " + o + " t:" + throwable);
    }
});

// block 2
p.then(new DonePipe() {
    @Override public Promise pipeDone(Object o) {
        Promise p2 = dm.when(new DeferredAsyncTask<Void, Integer, Object>() {
            @Override protected String doInBackgroundSafe(Void... nil) throws Exception {
                Log.v(TAG, "+++++++ BACKGROUND SLEEP 2");
                Thread.sleep(4000);
                int i = 1 / 0;
                Log.v(TAG, "+++++++ BACKGROUND RESUME 2");
                return "done 2";
            }
        });
        return p2;
    }
}).always(new AlwaysCallback<Object, Throwable>() {
    @Override
    public void onAlways(Promise.State state, Object o, Throwable throwable) {
        Log.v(TAG, "+++++++ ALWAYS 2 " + state.toString() + " o: " + o + " t:" + throwable);
    }
});

// block 3
p.then(new DonePipe() {
    @Override public Promise pipeDone(Object o) {
        Promise p3 = dm.when(new DeferredAsyncTask<Void, Integer, Object>() {
            @Override protected String doInBackgroundSafe(Void... nil) throws Exception {
                Log.v(TAG, "+++++++ BACKGROUND SLEEP 3");
                Thread.sleep(4000);
                Log.v(TAG, "+++++++ BACKGROUND RESUME 3");
                return "done 3";
            }
        });
        return p3;
    }
}).always(new AlwaysCallback<Object, Throwable>() {
    @Override
    public void onAlways(Promise.State state, Object o, Throwable throwable) {
        Log.v(TAG, "+++++++ ALWAYS 3 " + state.toString() + " o: " + o + " t:" + throwable);
    }
});

FAQ: how to asynchronously create a chain of deffered.

Hi all.
I am quite newbie with jdeffered terminology.
I will try to tell my problem.
And expect that you can translate it correctly in JDeffered terms.

Use case:
I have a big file containing a list of URLs.
I just have an implemented method called getContentFromTheWeb().
That method accepts a URL string as parameter and return as a String the corresponding content from the Web.

I wish I could use a syntax a la JDeffered to run this kind of code:
readURLsFromFileAsynchronously().asSoonAsAURLIsReadDoAsynchronously(getContentFromTheWeb(url)).afterAllURLsWereRetrieved(zipTheContents(listOfContentsAsString))

I am not sure JDeffered has such a direct compact syntax for this use case.
Anyway I hope gurus can help me get the shortest JDeffered code that implements this use case.
That would help me understand the underlying philosophy of JDeffered.

Any help is welcome.

Make jdeferred-android.jar available

While jdeferred-core.jar is available on Maven, jdeferred-android.jar is not (apklib, etc are there), and there seems to be no other distribution repository. This creates a high barrier to use for those people who don't use Maven.

A related problem is that it's not documented which libraries are needed for an Android App:
jdeferred-core
jdeferred-android
slf4j-api (this one is hard to guess from the myriad libraries for slf4j)
slf4j-android

GWT and bridge to jQuery

Hello,
Thanks for jdeferred, this is a nice and clean piece that I was missing.
I forked it to add support for GWT:

lbovet@002eac3

I provided a wrapper to transparently bridge jQuery promises to JDeferred promises which can be really useful for people integrating GWT and jQuery.

I did not submit a pull request because I made a change in AbstractPromise replacing the CopyOnWriteArrayList with ArrayList since the former is not supported by GWT. This change is OK for the GWT case, as all changes occur in the same thread but is obviously not true in the general case.

I hope to find a way to instruct GWT to replace this class by itself and keep the codebase correct for the general use.

I also had to change the logging to use java.util.logging but this is less an issue, I think.

Can you have a look at this and tell me if you would consider integrating this in JDeferred?

Enhancement: allow filterDone throw exception.

Currently we cannot throw exception in filterDone, a better approach is capture the exception in FilteredPromise and mark it as rejected. Let me use an example to explain this.

We need to do two things, one is get data through http, the other is convert the data (string) to domain object.

XHR.get(url).then(new DoneFilter<String, DomainObject>() {
DomainObject filterDone(String data) {
return DomainObject.parse(data); // no exception allowed.
}
});

Becasue of no exception allowed, we have to use following workaround.

XHR.get(url).then(new DonePipe<String, DomainObject, Throwable, Progress>() {
Promise<DomainObject, Throwable, Progress> pipeDone(String data) {
DeferredObject<> deferred = new DeferredObject<>();
try {
DomainObject obj = DomainObject.parse(data);
deferred.resolve(obj);
} catch (Throwable e) {
deferred.reject(e);
}
return deferred.
}
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.