Show List

Callback and future

Callbacks and futures are both mechanisms commonly used in asynchronous programming, but they have certain limitations that reactive programming seeks to address. Let's discuss each briefly with code examples:

  1. Callbacks: Callbacks are functions passed as arguments to other functions to be executed once the operation completes. They have been widely used in asynchronous programming in languages like JavaScript and early versions of Java.

    Example (Java):


    interface Callback { void onComplete(String result); } class AsyncOperation { void doSomethingAsync(Callback callback) { // Simulating asynchronous operation new Thread(() -> { // Asynchronous operation completes String result = "Operation completed"; callback.onComplete(result); }).start(); } } public class Main { public static void main(String[] args) { AsyncOperation asyncOp = new AsyncOperation(); asyncOp.doSomethingAsync(result -> { System.out.println("Received result: " + result); }); } }
  2. Future: Futures represent the result of an asynchronous computation. They allow you to check if the computation is done, and if so, to retrieve the result.

    Example (Java):


    import java.util.concurrent.*; public class Main { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executor = Executors.newSingleThreadExecutor(); Future<String> futureResult = executor.submit(() -> { // Simulating asynchronous operation Thread.sleep(1000); // Simulate delay return "Operation completed"; }); // Do some other work while waiting for the result System.out.println("Do something else..."); String result = futureResult.get(); // Blocking call to get the result System.out.println("Received result: " + result); executor.shutdown(); } }

Now, why these options are not considered good for asynchronous programming:

  1. Callback Hell: Using callbacks can lead to deeply nested and difficult-to-read code, known as "callback hell," especially when dealing with multiple asynchronous operations or error handling.

  2. Error Handling: Error handling in callback-based code can be challenging, often leading to error-prone and verbose code.

  3. Composition: It's difficult to compose multiple asynchronous operations using callbacks or futures, making it hard to express complex asynchronous workflows in a clear and concise manner.

  4. Backpressure: Neither callbacks nor futures provide built-in support for backpressure, which is crucial for handling scenarios where the producer is faster than the consumer in stream processing scenarios.

Reactive programming addresses these limitations by providing higher-level abstractions and compositional operators for working with asynchronous data streams, making it easier to express complex asynchronous behavior, handle errors, and manage backpressure effectively. This is why reactive programming, particularly when combined with libraries like Spring WebFlux, has become a popular choice for building asynchronous and reactive applications.


    Leave a Comment


  • captcha text