Java how to implement a callback hell (Callback Hell)?

For callback hell (Callback hell), presumably everyone is familiar with, especially for the front of friends, of course, the front of friends through a variety of ways to avoid callback hell, such as Promise. But for friends back end, especially after the rise of RxJava, Reactor and other reactive programming framework for the callback hell just hear more, but the less appear.

In order to better understand the callback hell Callback hell what the problem, we first need to learn how to write a callback hell. Before, we have to know what is the callback function.

This article will include:

  • What is a callback
  • Callback advantage
  • What the hell is a callback
  • Why is there a callback hell
  • What is the difference callback and Future
  • How to solve the callback hell

Today, we talk from the very beginning, to talk about what is the callback function.

What is a callback function?

On Baidu Encyclopedia, it says so:

The callback function is a function call through a function pointer. If you put the pointer (address) function as a parameter to another function, when the pointer is used to call the function it points to, we say this is a callback function. Callback function is not called directly by the parties to achieve the function, but by another calling party when a particular event or condition occurs, for response to the event or condition. Callback is a method call is any other method to its first argument of the method. In many cases, a callback method is when certain events occur is called.

what? Difficult to understand? Indeed difficult to understand and interpret this as well as pointers and so on, it is for java user unfriendly.

Give you an example, for your reference, also welcome criticism:

Recall: the caller after a call to the called party, the called party will be the results back to the caller. (A calls B, B after completion, the results back to A)

For example: your boss employee a job, employees to complete. After the staff to complete the work, the boss feedback results of the work. This process is called a callback.

Callback example
Callback example

This time is easy to understand a lot of it! Talk is cheap, Show me the code! Well, we will use this to write a simple example.

Callback example

Callback Interface

First of all, let's write a following Callbackinterface, the interface contains only one method for callback operations.

/**
 * @author yangzijing
 */
public interface Callback<T> {

    /**
     * 具体实现
     * @param t
     */
    public void callback(T t);

}
复制代码

Boss class

The boss is the feedback of the object, so the need to implement Callbackthis interface, overloaded callbackmethods; for specific boss to do, of course, is big business, so have the makeBigDealsmethods; the boss of course, can not be without an army, he needs a staff, we'll constructor he was to add a staff Worker, we later realized Worker class.

public class Boss implements Callback<String> {

    private Worker worker;

    public Boss(Worker worker) {
        this.worker = worker;
    }

    @Override
    public void callback(String s) {
    }

    public void makeBigDeals(final String someDetail) {
		worker.work(someDetail);
    }

}
复制代码

Worker Class

Employees class, quite simply, out of a job, completed just fine, the result can be returned. But how to complete the callback?

public class Worker {
    public String work(String someWork) {
		return 'result';
    }
}
复制代码

It is easy to think of this idea is very logical thinking, but in the callback, we need to make some changes.

Make up the code callback

For employees, the need to know two things, who is the boss, need doing. Thus, the two input parameters, namely, the boss and job content. Specific content in two steps, first completing its mission, is to report to the boss.

public class Worker {
    public void work(Callback<String> boss, String someWork) {
		String result = someWork + 'is done!'; // 做一些具体的处理
		boss.callback(result); // 反馈结果给老板
    }
}
复制代码

Next, we complete the Boss class. In the callbackmethod, the received results came, and the results are processed, we only print out here; in the makeBigDealsprocess, the boss assigning work, staff to complete, if the complete process is asynchronous , it is 异步调用, if it is synchronized , the Shi 同步回调, we are here asynchronously.

In the new thread, we execute worker.work(Boss.this, someDetail), which Boss.thisis the current object, here we officially completed callback .

public class Boss implements Callback<String> {
    ……
    @Override
    public void callback(String result) { // 参数为worker输出的结果
		logger.info("Boss got: {}", result) // 接到完成的结果,并做处理,在这里我们仅打印出来
	}

    public void makeBigDeals(final String someDetail) {
		logger.info("分配工作");
		new Thread(() -> worker.work(Boss.this, someDetail)); // 异步完成任务
		logger.info("分配完成");
		logger.info("老板下班。。");
    }
}
复制代码

Callback results

Show me the result! Well, try to run the code.

Worker worker = new Worker();
Boss boss = new Boss(worker); // 给老板指派员工
boss.makeBigDeals("coding"); // 老板有一个代码要写
复制代码

The results are as follows. Can be seen in the results, the boss got off work after the completion of the distribution of work, after work, another thread notifies owners receive feedback "coding is done". So far, we have completed the asynchronous callback entire process.

INFO  2019 九月 20 11:30:54,780 [main]  - 分配工作
 INFO  2019 九月 20 11:30:54,784 [main]  - 分配完成
 INFO  2019 九月 20 11:30:54,784 [main]  - 老板下班。。
 INFO  2019 九月 20 11:30:54,787 [Thread-0]  - Boss got: coding is done!
复制代码

I will spread code examples Github, for your reference. callback code sample

Callback advantage

  • Decoupling , the correction sub-process from the main process Decoupling. For the same input, that might be of a different approach. In the callback function, we have completed the main flow (e.g. the above Bosstype), for the sub-processes (e.g., the above process Workeris separated from the main flow out of the class). For the main process, we only care about the input and output of the sub-processes, that is input in the example above Worker.workparameters, and outputs the sub-process is the main process callbackparameters of the method.
  • Asynchronous callback does not block the main thread. The above example can be seen clearly, the staff did not work before the boss has been completed after work, when the work is completed, the owner will be notified by another thread. The boss in this process without waiting for the child process.

Callback Hell

The overall design

We will extend the above functions, work to the boss first product manager for design; the design is complete, the programmer to complete the coding. A schematic process shown in FIG.

Callback Hell
Callback Hell

The tasks to Product Manager

First, write a Callback, a new internal product manager of Worker, in makeBigDealrealization of the main tasks of the methods, the task to Product Manager; in overloaded callbackmethod to obtain the output product manager.

new Callback<String>() {
            private Worker productManager = new Worker();
            @Override
            public void callback(String s) {
                System.out.println("产品经理 output: " + s); // 获取产品经理的输出
            }

            public void makeBigDeals(String bigDeal) {
                System.out.println("Boss将任务交给产品");
                new Thread(() -> {
                    this.productManager.work(this, bigDeal); // 异步调用产品经理处理过程
                }).start();
            }
        }.makeBigDeals("design");
复制代码

Then output to the developer product manager

After the product manager to get the output, and then output to the developer. So we again achieved a Callbackinterface. Similarly, Callbackin the development of a new new Worker, in the codingprocess, calls Workerfor development; the overloaded callbackmethod, obtaining the result of the development process.

@Override
public void callback(String s) {
	System.out.println("产品经理 output: " + s); // 产品经理的输出
	String midResult = s + " coding";
	System.out.println("产品经理设计完成,再将任务交给开发");
	new Callback<String>() {
		private Worker coder = new Worker();

		@Override
		public void callback(String s) {
			System.out.println("result: " + s); // 获取开发后的结果
		}

		public void coding(String coding) {
			new Thread(() -> coder.work(this, coding)).start(); // 调用开发的Worker进行开发
		}
	}.coding(midResult); // 将产品经理的输出交给开发
}
复制代码

Complete implementation

new Callback<String>() {
            private Worker productManager = new Worker();
            @Override
            public void apply(String s) {
                System.out.println("产品经理 output: " + s);
                String midResult = s + " coding";
                System.out.println("产品经理设计完成,再将任务交给开发");
                new Callback<String>() {
					private Worker coder = new Worker();
                    @Override
                    public void apply(String s) {
                        System.out.println("result: " + s);
                    }
                    public void coding(String coding) {
                        new Thread(() -> coder.work(this, coding)).start();
                    }
                }.coding(midResult);
            }

            public void makeBigDeals(String bigDeal) {
                System.out.println("Boss将任务交给产品");
                new Thread(() -> this.productManager.work(this, bigDeal)).start();
            }
        }.makeBigDeals("design");
复制代码

Well, a simple callback hell is complete. Show me the result!

Boss将任务交给产品
产品经理 output: design is done!
产品经理设计完成,再将任务交给开发
result: design is done! coding is done!
复制代码

Callback hell brought what?

In the end what is a callback hell? Simply put, the callback hell is inside and set up a Callback Callback, but if nesting too much, as if falling into hell, so to hell with the callback argument.

Advantage: What the hell callback bring to us? In fact, the callback code the same as the pipe , received input, and outputs the processed contents to the next step . And callback hell, is a plurality of pipe connections, a process of forming, and the respective sub-flow (pipe) independently of one another. The distal end may be more familiar friends, for example Promise.then().then().then(), is formed of a plurality of process flow line.

Disadvantages: the callback method, although the sub-processes decoupling, but the callback code readability reduces complexity greatly increased.

Callback Hell示例:Callback Hell

Comparison and Future

Above, we mentioned asynchronous callback does not block the main thread, then use the Future will not be blocked, and asynchronous callback difference in what?

We write an example of using the asynchronous call to the Future:

logger.info("分配工作...");
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> worker.work(someDetail));
logger.info("分配完工作。");
logger.info("老板下班回家了。。。");
logger.info("boss got the feedback from worker: {}", future.get());
复制代码

In the above code, we can see that although Workerthe work is asynchronous, but the boss get the results of the work ( future.get()) when they have to wait, and wait for this process is blocked. This is the callback and Future a significant difference.

Comparison and Future of callback: callback and future comparison

How to solve

How to solve the problem of callback hell, the most common is reactive programming RxJava and the Reactor , there Kotlin of Coroutine coroutine, OpenJDK out of the Project Loom . Which have their own advantages, refrain from that.

to sum up

in conclusion:

  1. What is a callback . The caller callback is invoked after the called party, the called party will feedback the results to the caller. (A calls B, B after completion, the results back to A)
  2. Callback advantage . 1) sub-process and the main process decoupled. 2) an asynchronous call and do not block the main thread.
  3. What callback hell . Hell is a callback function callback nested, and more to see =. =
  4. Why the hell callback occurs . Each callback like a pipeline, receiving the output, the output after the processing result to the next pipe. Each independent processing pipeline, composed of a plurality of pipes entire process.
  5. What is the difference callback and Future . 1) difference between the two mechanisms; 2) Future will be blocked while waiting for the results, but the callback does not block.
  6. How to solve the callback hell . The most common is reactive programming RxJava and Reactor.

Guess you like

Origin juejin.im/post/5d84a0f26fb9a06acf2b94ea