Eloquent JavaScript - Bugs and Errors

387 阅读1分钟

练习题

题一:Retry

Say you have a function primitiveMultiply that in 20 percent of cases multiplies two numbers and in the other 80 percent of cases raises an exception of type MultiplicatorUnitFailure. Write a function that wraps this clunky function and just keeps trying until a call succeeds, after which it returns the result.

Make sure you handle only the exceptions you are trying to handle.

我最开始写了一个复杂的版本,用到了try catch finally

class MultiplicatorUnitFailure extends Error{} 

function primitiveMultiply(x, y) {
    let randomNumber = Math.trunc(Math.random() * 101);
    console.log(randomNumber);    // 查看生成的randomNumber到底是多少
    if (randomNumber <= 20) return x * y;
    else {
        throw new MultiplicatorUnitFailure();
    }
}

function multiplication(x, y) {
    let multiplicationResult = undefined;
    let retry = 1;
    while (retry) {
        try {
            multiplicationResult = primitiveMultiply(x, y);
        } catch (error) {
            if (error instanceof MultiplicatorUnitFailure) {
                console.log("Continue to call the primitiveMultiply()");
            }
        } finally {
            if (multiplicationResult !== undefined) {
                console.log("We have got the multiplication result. ");
                retry = null;
            }
        }
    }

    return multiplicationResult;
} 

第二次,我对multiplication(x, y)进行了改进,只用到try catch

function multiplication(x, y) {
    let multiplicationResult = undefined;
    let retry = 1;
    while (retry) {
        try {
            multiplicationResult = primitiveMultiply(x, y);
            retry = null;
        } catch (error) {
            if (error instanceof MultiplicatorUnitFailure) {
                console.log("Continue to call the primitiveMultiply()");
            }
        }
    }

    return multiplicationResult;
}

因为当程序运行到retry = null的时候,说明上一行的代码已经顺利完成,就可以跳出while循环了。
作者给出的答案如下:

class MultiplicatorUnitFailure extends Error {}

function primitiveMultiply(a, b) {
    if (Math.random() < 0.2) {
        return a * b;
    } else {
        throw new MultiplicatorUnitFailure('Klunk');
    }
}

function reliableMultiply(a, b) {
    for (;;) {
        try {
            return primitiveMultiply(a, b);
        } catch (e) {
            if (!(e instanceof MultiplicatorUnitFailure)) throw e;
        }
    }
}

也就是说,作者用到的是for(;;),学到了,哈哈哈。return primitiveMultiply(a, b)这一行代码顺利执行完(没有throw exception),自然就跳出了for loop。