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
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;
}