JavaScript - Retry函数引起的思考

昨天领导提了一个问题,需要创建一个retry函数,目的是为了执行某一个函数,当函数执行成功则返回正确的结果,如果执行失败则需要在1000ms内执行当前函数4次直到返回正确结果,如果1000ms内还没有返回结果,则需要返回错误提示信息。 

第一版

拿到这个问题之后,一顿操作猛如虎,其实没有什么用。

var executeFunction = function() {
    var timespan = 250;
    var maxCount = 4;
    var executeCount = 0;

    var success = function() {
        console.log('success');
    }

    var fail = function() {
        console.log('fail');
    }

    return function(callback) {
        setTimeout(function() {
            if (callback()) {
                return success();
            } else if (++executeCount < maxCount) {
                arguments.callee();
            } else {
                return fail();
            }
        }, timespan);
    }
}

var testFunction = function() {
    var date = new Date();

    console.log("execute testFunction: Date " + date.toString() + ". ms: " + date.getMilliseconds() );
    return false;
}

executeFunction()(testFunction);

执行结果如下:


个人说明: 因为给的这个需求自己一开始没有搞清楚,然后leader要求5分钟再黑板上写出来。上面的这个版本也没有写完,上面的代码是我按照一开始的想法后续加上的。可以看到当前的执行时间间隔不是250ms。

执行这个结果的原因:

因为arguments.callee()指向的是当前执行的函数,当前执行的函数是setTimeout的第一个参数匿名函数,不是当前返回的函数,所以结果是错误的,因为后续的执行根本不走setTimeout。

第二版

找到原因之后,我将返回的函数加上了一个名称当成具名函数,然后再去调用这个函数就可以了。

var executeFunction = function() {
    var timespan = 250;
    var maxCount = 4;
    var executeCount = 0;

    var success = function() {
        console.log('success');
    }

    var fail = function() {
        console.log('fail');
    }

    return function returnFunction(callback) {
        setTimeout(function() {
            if (callback()) {
                return success();
            } else if (++executeCount < maxCount) {
                returnFunction(callback);
            } else {
                return fail();
            }
        }, timespan);
    }
}

var testFunction = function() {
    var date = new Date();

    console.log("execute testFunction: Date " + date.toString() + ". ms: " + date.getMilliseconds() );
    return false;
}

executeFunction()(testFunction);


leader的本意

其实在我们将代码书写在黑板上写过之后,当然没有完成。leader说当我看到你们写代码的时候,你们写代码是在做1+1=2的过程。

这个1+1=2的含义是什么呢?(在领导的抽象说明之后的个人臆测)

写代码的时候上来就是一些不是关键的东西写出来了,例如1000ms,执行4次的条件在代码了写出来了。


如上图:我们其实将这个问题的分析走了一个逆向的思维,是先考虑了比较detail的问题,然后执行1+1最后生成最后的代码。

leader的本意应该如下(当然还是我的臆测)

leader的想法是让我们做f(x, y),让我们从上往下考虑。



/*retry*/  
var retry = function(functionName, retryCondition, retryConfig) {  
    if (typeof functionName != 'function') {  
        return "functionName should be function!";  
    }  
  
    if (typeof retryCondition != 'function') {  
        return "retryCondition should be function!";  
    }  
  
    if (typeof retryConfig != 'object') {  
        return "retryConfig should be object!";  
    } 


    retryConfig.retryTimeRange = retryConfig.retryTimeRange || 0;
    retryConfig.retryCount = retryConfig.retryCount || 1;
  
    var returnValue = functionName();  
    var retryIndex = 0;  
  
    if (!retryCondition(returnValue)) {  
        return returnValue;  
    } else {  
        var retryTimeSpan = retryConfig.retryTimeRange / retryConfig.retryCount;  
  
        (function retry() {  
            setTimeout(function() {  
                var returnValue = functionName();  
  
                if (!retryCondition(returnValue)) {  /*return true will try*/  
                    return returnValue;  
                } else if (++retryIndex < retryConfig.retryCount) {  
                    retry();  
                } else {  
                    console.info("fail returnvalue: " + returnValue);  
                    return returnValue;  
                }  
            }, retryTimeSpan);  
        })(functionName);  
    }  
}  
  
/*test*/  
var functionName1 = function() {  
    var returnValue = Math.random() * 100;  
  
    /*log innfo*/  
    var date = new Date();  
    console.info("execute testFunction: Date " + date.toString() + ". ms: " + date.getMilliseconds() );  
    console.info("returnvalue: " + returnValue);  
  
    return returnValue;  
}  
  
var retryCondition1 = function(returnValue) {  
    if (returnValue > 80) {  
        return false;  
    }   
  
    return true;  
}  
  
var retryConfig1 = {  
    retryTimeRange: 1000,  
    retryCount: 5  
}  
  
retry(functionName1, retryCondition1, retryConfig1);  
我们看一下返回的结果(这里的测试是使用随机数返回值,如果随机数*100 > 80则返回值,如果retry时间到了还没有正确答案,则返回值并标明是错误的结果的),下面的三次返回前两次存在正确返回值,最后一次五次retry还是没有正确的返回值。

延伸:如何处理Ajax,我的想法是借助Promise,这样我们可以控制函数执行什么时候返回结果。我认为只要将Promise包装函数就可以了。

写到这里,上文都是自己的一些感悟吧,无论对错,希望大家指出来不对和改进的地方。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值