let x; try { x = ...; } catch (e) { return } // rest of the code that uses `x` const y = x + ...;
x只分配了一次,但我必须使用let而不是const.
另一种方式是:
try { const x = ...; // rest of the code that uses `x` const y = x + ...; } catch (e) { return }
有没有更好的办法?
如果尝试失败,我不必关心x的值,因为我将在catch块中返回.
我也不想将其解析为单独的函数.
解决方法
功能 – 使用带有三个回调的辅助函数:
function Try(attempt,onSuccess,onFailure) { try { var res = attempt(); } catch(err) { return onFailure(err); } return onSuccess(res); }
这允许你写
return Try(() => …,x => { // rest of the code that uses `x` const y = x + …; },e => void e);
您还可以使用表示此控制流的数据结构,如Result monad(也称为Either monad):
class Result { constructor(go) { this.go = go; } static Ok(v) { return new this((onSuccess,_) => onSuccess(v)); } static Err(r) { return new this((_,onFailure) => onFailure(v)); } map(f) { return this.go(v => Result.Ok(f(v)),r => Result.Err(r)); } chain(f) { return this.go(v => f(v),r => Result.Err(r)); } unwrap() { return this.go(v => v,r => { throw r; }); } } function Try(attempt) { try { var res = attempt(); return Result.Ok(res); } catch(e) { return Result.Err(e); } }
你可以使用它与上面简单的辅助函数非常相似:
return Try(() => … // exceptions in here are caught ).go(x => { // rest of the code that uses `x` - exceptions are not caught const y = x + …; },e => void e);
但也有更先进的链接:
return Try(() => … // exceptions in here are caught ).chain(x => Try(() => x + … // exceptions in here are caught as well ) ).map(y => … // exceptions in here are not caught ).unwrap(); // any caught exceptions are re-thrown