Strange js callback chaos
A piece of code was found today, and a strange callback disorder occurred.
The called API is as follows:
api.method = function(sql, condition, successCallback, failureCallback){ // logic}
Our Own Business Code calls this function:
var sql = "insert into xxxx";var condition = {};api.method(sql, condition, function(result){ // callback when success}, function(err){ // callback when error});
The original understanding should be that after calling this function, if the result is correct, the first callback function will be called; otherwise, the second callback function will be called. In fact, we found that the first callback function was indeed called, but it was not completed and suddenly jumped to the Second callback function.
Finally, I had to go to the source code of api. method and find that it was handled like this internally:
api.method = function(sql, condition, successCallback, failureCallback){ var result = {}; // do some logic if(err){ failureCallback(err); return; } try{ successCallback(result); }catch(err){ failureCallback(err); }}
As shown above, successCallback is enclosed by try... catch. if an exception is thrown during successCallback execution, successCallback is aborted and failureCallback is executed. Then we checked our successCallback, and a line of code throws an exception.
Thoughts:
1. In our code, try... catch is rarely used. In fact, the code is still relatively fragile. Such errors are difficult to locate, and sometimes they can't be found because they have made mistakes silently for a long time. Therefore, it may be better to add try... catch in the case of errors. In this regard, JAVA is better. Although CheckedException and UncheckedException have been criticized by many people, it is complicated and not elegant, but it is helpful in exception capture and locating.
2. In my opinion, the above API design is not totally unreasonable. In the case of a successful callback error, you can jump to the error callback, which is quite clever. But it is only valid for Synchronous methods. If my successful callback contains an asynchronous function, it still cannot capture errors in the asynchronous function, so it is not very reliable. In addition, interrupting One callback and redirecting to another callback is an obvious hidden rule, which will definitely make the caller misunderstand. Therefore, adding comments and logs will be much better.