]> source.dussan.org Git - gwtquery.git/commitdiff
Fix "then()" method so as it behaves like jQuery breaking the flow if previous fails...
authorManuel Carrasco Moñino <manuel.carrasco.m@gmail.com>
Sat, 9 Nov 2013 09:56:51 +0000 (10:56 +0100)
committerManuel Carrasco Moñino <manuel.carrasco.m@gmail.com>
Sat, 9 Nov 2013 09:56:51 +0000 (10:56 +0100)
gwtquery-core/src/main/java/com/google/gwt/query/client/Promise.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/deferred/Deferred.java
gwtquery-core/src/test/java/com/google/gwt/query/client/deferred/DeferredTest.java

index bb6a8e1372817c192dfb9721c4496d69fd6a26bf..cc2b0f6175de9848ba220647b4ff6fdc035dade8 100644 (file)
@@ -101,6 +101,45 @@ public interface Promise {
    */
   Promise then(Function... f);
   
+  /**
+   * Add filters to be called just in case the Deferred object is rejected returning
+   * a new valid promise so as we can continue the flow control of the chain.
+   *
+   * It works in the same way than adding a second parameter to {@link then} method but 
+   * continuing the flow and making more readable the code.
+   *
+   * NOTE: this method is in gQuery but not in jQuery.
+   *
+   * Example:
+   * <pre>
+     GQuery.when(gettingConfigurationFromCache())
+           .or(gettingConfigurationFromServer())
+           .done(drawUI());
+   * </pre>
+   *
+   * NOTE: this is a convenience method in gQuery not present in jQuery.
+   */
+  Promise or(Function f);
+
+  /**
+   * Add filters to be called just in case the Deferred object is resolved.
+   *
+   * It works in the same way than {@link then} does but making more readable
+   * the code flow.
+   *
+   * NOTE: this method is in gQuery but not in jQuery.
+   *
+   * Example:
+   * <pre>
+     GQuery.when(login())
+           .and(getConfiguration())
+           .done(drawUI());
+   * </pre>
+   *
+   * NOTE: this is a convenience method in gQuery not present in jQuery.
+   */
+  Promise and(Function f);
+
   /**
    * Determine whether a Deferred object has been resolved.
    */
index 5be4892cb5310b90e2340f2622e524ae27a6269a..c07fee40145fa2627220aadc73a577a836ddf122 100644 (file)
@@ -15,9 +15,7 @@
  */
 package com.google.gwt.query.client.plugins.deferred;
 
-import static com.google.gwt.query.client.Promise.PENDING;
-import static com.google.gwt.query.client.Promise.REJECTED;
-import static com.google.gwt.query.client.Promise.RESOLVED;
+import static com.google.gwt.query.client.Promise.*;
 
 import com.google.gwt.query.client.Function;
 import com.google.gwt.query.client.GQuery;
@@ -38,18 +36,6 @@ public class Deferred implements Promise.Deferred {
 
     // Private class used to handle `Promise.then()`
     private static class ThenFunction extends Function {
-      // Used internally in ThenFunction, to resolve deferred object
-      private class DoFunction extends Function {
-        int type;
-        public DoFunction(int type) {
-          this.type = type;
-        }
-        public void f() {
-          if (type == DONE) dfd.resolve(getArguments());
-          if (type == FAIL) dfd.reject(getArguments());
-          if (type == PROGRESS) dfd.notify(getArguments());
-        }
-      }
 
       // Original filter function
       private final Function filter;
@@ -57,35 +43,55 @@ public class Deferred implements Promise.Deferred {
       private final int type;
       // Original deferred object
       private final Deferred dfd;
+      // Whether break the flow if old deferred fails
+      boolean cont = false;
 
-      public ThenFunction(Deferred newDfd, Function[] subordinates, int funcType) {
+      public ThenFunction(Deferred newDfd, Function[] subordinates, int funcType, boolean continueFlow) {
         type = funcType;
         filter = subordinates.length > type ? subordinates[type] : null;
         dfd = newDfd;
+        cont = continueFlow;
       }
 
       public void f() {
-        final Object[] args = getArguments();
-        Function doIt = new DoFunction(type).setArguments(args);
+        final Object[] oldArgs = getArguments();
         if (filter != null) {
           // We filter resolved arguments with the filter function
-          Object newArgs = filter.setArguments(args).f(args);
-          // If filter function returns a promise we pipeline it and don't resolve this
+          Object newArgs = filter.setArguments(oldArgs).f(oldArgs);
+
           if (newArgs instanceof Promise) {
-            Promise p = (Promise) newArgs;
-            p.done(new DoFunction(DONE));
-            p.fail(new DoFunction(FAIL));
-            p.progress(new DoFunction(PROGRESS));
-            return;
-          // Otherwise we change the arguments with the new args
-          } else if (newArgs != null && newArgs.getClass().isArray()) {
-            doIt.setArguments((Object[])newArgs);
+            // If filter function returns a promise we pipeline it.
+            final Promise p = (Promise) newArgs;
+            if (type == PROGRESS) {
+              p.progress(new Function(){public void f() {
+                settle(PROGRESS, getArguments());
+              }});
+            } else {
+              p.always(new Function(){public void f() {
+                if (p.isRejected() && !cont) {
+                  settle(FAIL, getArguments());
+                } else {
+                  settle(DONE, getArguments());
+                }
+              }});
+            }
+          
           } else {
-            doIt.setArguments(newArgs);
+            // Otherwise we change the arguments by the new ones
+            newArgs = Boolean.TRUE.equals(newArgs) ? oldArgs :
+                      newArgs != null && newArgs.getClass().isArray() ? (Object[])newArgs : newArgs;
+            settle(type, newArgs);
           }
+        } else {
+          // just continue the flow when filter is null
+          settle(type, oldArgs);
         }
-        // run the function with the new args to resolve this deferred
-        doIt.f();
+      }
+      
+      private void settle(int action, Object... args) {
+        if (action == DONE) dfd.resolve(args);
+        if (action == FAIL) dfd.reject(args);
+        if (action == PROGRESS) dfd.notify(args);          
       }
     }
     
@@ -141,7 +147,11 @@ public class Deferred implements Promise.Deferred {
     public Promise always(Function... f) {
       return done(f).fail(f);
     }
-
+    
+    public Promise and(Function f) {
+      return then(f);
+    }
+    
     public Promise done(Function... f) {
       dfd.resolve.add(f);
       return this;
@@ -151,7 +161,11 @@ public class Deferred implements Promise.Deferred {
       dfd.reject.add(f);
       return this;
     }
-
+    
+    public Promise or(final Function f) {
+      return then(false, null, f);
+    }   
+    
     public Promise pipe(Function... f) {
       return then(f);
     }
@@ -165,13 +179,17 @@ public class Deferred implements Promise.Deferred {
       return dfd.state;
     }
 
-    public Promise then(final Function... f) {
+    private Promise then(boolean continueFlow, final Function... f) {
       final Deferred newDfd = new com.google.gwt.query.client.plugins.deferred.Deferred();
-      done(new ThenFunction(newDfd, f, DONE));
-      fail(new ThenFunction(newDfd, f, FAIL));
-      progress(new ThenFunction(newDfd, f, PROGRESS));
+      done(new ThenFunction(newDfd, f, DONE, continueFlow));
+      fail(new ThenFunction(newDfd, f, FAIL, continueFlow));
+      progress(new ThenFunction(newDfd, f, PROGRESS, continueFlow));
       return newDfd.promise();
     }
+    
+    public Promise then(final Function... f) {
+      return then(false, f);
+    }
 
     public boolean isResolved() {
       return Promise.RESOLVED.equals(state());
index 6e3da0964fac3dbc92e0f017769e6cc96cb9b9bc..8537b34b0ee428692bf85f5bff7b1d0012c65a3d 100644 (file)
@@ -211,7 +211,7 @@ public class DeferredTest extends GWTTestCase {
           dfd.resolve("message");
         }
       })
-      .then(new FunctionDeferred() {
+      .and(new FunctionDeferred() {
           public void f(Deferred dfd) {
             dfd.resolve("then1 " + arguments[0]);
           }
@@ -250,14 +250,24 @@ public class DeferredTest extends GWTTestCase {
           dfd.resolve("message");
         }
       })
+      .and(new Function(){
+        public Object f(Object... data) {
+          return (arguments[0] + " then1");
+        }
+      })
+      .then(new Function(){
+        public void f() {
+          // should return the previous value
+        }
+      })
       .then(new FunctionDeferred() {
           public void f(Deferred dfd) {
-            dfd.resolve("then1 " + arguments[0]);
+            dfd.reject("then2 " + arguments[0]);
           }
       })
       .then(new FunctionDeferred() {
           public void f(Deferred dfd) {
-            dfd.reject("then2 " + arguments[0]);
+            dfd.resolve("then3 " + arguments[0]);
           }
       })
       .done(new Function() {
@@ -268,7 +278,7 @@ public class DeferredTest extends GWTTestCase {
       })
       .fail(new Function() {
         public void f() {
-          assertEquals("then2 then1 message", arguments(0));
+          assertEquals("then2 message then1", arguments(0));
           finishTest();
           done = true;
         }
@@ -278,6 +288,60 @@ public class DeferredTest extends GWTTestCase {
       assertTrue(done);
     }    
   }
+  
+  public void testDeferredOr() {
+    done = false;
+    delayTestFinish(5000);
+
+    GQuery
+      .when(new PromiseFunction() {
+        public void f(Deferred dfd) {
+          dfd.reject("reject-when");
+        }
+      })
+      .or(new FunctionDeferred() {
+        public void f(Deferred dfd) {
+          dfd.reject(arguments[0] + " reject-or1");
+        }
+      })
+      .or(new FunctionDeferred() {
+          public void f(Deferred dfd) {
+            dfd.reject(arguments[0] + " reject-or2");
+          }
+      })
+      .then(null, new FunctionDeferred() {
+          public void f(Deferred dfd) {
+            dfd.resolve(arguments[0] + " resolve-or3");
+          }
+      })      
+      .or(new FunctionDeferred() {
+          public void f(Deferred dfd) {
+            dfd.resolve(arguments[0] + " or4");
+          }
+      })      
+      .or(new FunctionDeferred() {
+        public void f(Deferred dfd) {
+          dfd.reject(arguments[0] + " or5");
+        }
+      })
+      .done(new Function() {
+        public void f() {
+          assertEquals("reject-when reject-or1 reject-or2 resolve-or3", arguments(0));
+          finishTest();
+          done = true;
+        }
+      })
+      .fail(new Function() {
+        public void f() {
+          finishTest();
+          fail();
+        }
+      });
+    
+    if (!GWT.isClient()) {
+      assertTrue(done);
+    }    
+  }
 
 
   public void testProtected() {