这就是我想做的:
var setting = process.env.SETTING || throw new Error("please set the SETTING environmental variable");
^^^^^
但是解释器抱怨“语法错误:意外的令牌抛出”。
有没有办法在我们比较值是否为假的同一行中抛出异常?
您可以利用 javascript 的函数性质。可以使用
function() {}()
立即调用函数(表达式)。这称为立即调用函数表达式 (IFFE)。
x || y
称为短路评估。
var setting = process.env.SETTING || function() {
throw "please set the SETTING environmental variable"; }();
// es201x
const setting = process.env.SETTING || ( () => {
throw `SETTING environmental variable not set`; } )();
或更通用的创建一个函数来抛出错误并使用它:
function throwErr(mssg){
throw new Error(mssg);
}
var setting = process.env.SETTING ||
throwErr("please set the SETTING environmental variable");
我使用的片段:
const throwIf = (
assertion = false, // default false
message = `An error occurred`, // default Error message string
ErrorType = Error // default errorType generic Error
) => {
// throw if assertion is true, otherwise do nothing
if (assertion) {
throw new ErrorType(message);
}
};
const windowSettingSet = window.SOMESETTING;
// !windowSettingSet is true, so will throw
throwIf(!windowSettingSet, `window.SOMESETTING not defined`, TypeError);
throw
是一个语句,而不是一个表达式,因此您不能将其用作另一个表达式的一部分。你必须把它分开:
var setting = process.env.SETTING;
if (!setting) throw new Error("please set the SETTING environmental variable");
有一个提案草案将 throw 表达式(类似于 C# 7 的 throw 表达式)引入 JavaScript/ECMAScript:
用牙套把它包起来
{throw ...}
或者用函数包裹它(实际上是把它包裹在大括号内)
()=>{throw ..}
//or:
function(){throw..}
throw
没有返回值。所以你不能那样使用它。但是,您可以将 throw 包装在函数中。那就行了。但要找到异常的根源会更加困难。
我看到你使用nodejs。
我认为验证输入参数的最好方法是断言。 NodeJS 内置了简单的断言模块:http://nodejs.org/api/assert.html
并使用它,例如,像这样:
var assert = require('assert');
// ...
function myFunction (param) {
assert(param, 'please pass param');
// ...
}
对于测试环境,你可以这样做:
require('assert')(process.env.setting, 'please set the SETTING environmental variable');
或者:
;(function (a) {
a(process.env.setting, 'please set the SETTING environmental variable');
a(process.env.port, 'please set the PORT environmental variable');
}(require('assert')));
const getenv = require('getenv');
const setting = getenv('SETTING');
如果 SETTING 不存在,您将得到:
… getenv.js:14
throw new Error('GetEnv.Nonexistent: ' + varName + ' does not exist ' +
^ Error: GetEnv.Nonexistent: SETTING does not exist and no fallback value provided.
顺便说一句,我的经验告诉我,环境变量的默认值是邪恶的。
不是问题的直接答案,但如果您使用 TypeScript,我发现 runtypes 是手动验证和抛出的绝佳替代方案。虽然 OP 中的方法在输入类型为
output | null | undefined
或类似类型时有效,但运行类型在输入类型为 any
时也有效,例如在防御性解码具有已知结构的 JSON 时。
你会像这样使用它:
import { String } from 'runtypes';
const setting = String.check(process.env.SETTING)
如果
process.env.SETTING
是 undefined
,则会抛出异常。添加 .withConstraint()
以添加其他条件。该库实际上非常强大,不仅可以验证简单类型,还可以以类型安全的方式验证记录(接口)、联合等。
一个缺点是您无法自定义错误消息(“约束检查失败”),这在许多快速而肮脏的情况下是可以的,因为发生错误的行会告诉您问题是什么。
io-ts 是另一个类似的库,尽管它似乎有更复杂的方法并且目前正在不断变化。
虽然不可能直接使用
throw
作为表达式,但它可以像 Koooilnc 那样用在立即调用的匿名闭包中,或者像 casablanca 那样分成自己的语句,或者用 Node 的 assert
替换
正如 Alex Yarochevich 建议的那样。
tiny-invariant
或类似的函数。
invariant(process.env.SETTING, "SETTING environment variable is required");
const setting = process.env.SETTING;
或
const setting = process.env.SETTING;
invariant(setting, "SETTING environment variable is required");
它比立即调用的匿名闭包更简单,比单独的 if-throw 语句更清晰、更短(因为条件没有反转),并且与 Node 的
assert
不同,适当缩小了 TypeScript 中的类型范围,并且可以在浏览器中使用。
它也比我之前的建议使用运行时类型库要轻量得多。