code: function interceptAsyncAPIDone(sync, args, doneHook) {
      let callOpts = args[0];
      let {success, fail, complete} = callOpts || {};
      let hasIntercepted = false;
  
      if (!sync
          && (isFunction(success) || isFunction(fail) || isFunction(complete))
      ) {
          hasIntercepted = true;
          let newCallOpts = Object.assign({}, callOpts);
          newCallOpts.success = res => {
              let data = doneHook(null, res, complete, true);
              success && success(data);
          };
  
          newCallOpts.fail = err => {
              err = doneHook(err || /* istanbul ignore next */ 'err', null, complete, true);
              fail && fail(err);
          };
  
          // remove complete callback
          // using success and fail callback instead of using complete callback
          complete && (newCallOpts.complete = undefined);
          args[0] = newCallOpts;
      }
  
      return hasIntercepted;
  }
docs: Intercept async API done based on the call arguments: `success`/`fail`
  
  @inner
  @param {boolean} sync whether is sync API, if true, it will not hook the
  API done result based the call arguments
  @param {Array} args the API call arguments
  @param {Function} doneHook the done hook to execute
  @return {boolean} whether intercept the API done result by the arguments