簡體   English   中英

在 Javascript 表達式中使用 throw

[英]Using throw in a Javascript expression

這是我想要做的:

var setting = process.env.SETTING || throw new Error("please set the SETTING environmental variable");
                                     ^^^^^

但是解釋器抱怨“語法錯誤:意外的令牌拋出”。

有沒有辦法在我們比較一個值是否為假的同一行中拋出異常?

您可以利用 javascript 的功能特性:

var setting = process.env.SETTING || 
               function(){ 
                 throw "please set the SETTING environmental variable";
               }();
// es201x
var 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, message = `An error occurred`, ErrorType = Error) => assertion && (() => { throw new ErrorType(message); })(); throwIf(!window.SOMESETTING, `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:

TC39 提案:拋出表達式

用大括號把它包起來

{throw ...}

或者用一個函數包裹它(女巫實際上將它包裹在大括號內)

()=>{throw ..}
//or:
function(){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')));

不是問題的直接答案,但如果您使用的是 TypeScript,我發現runtypes是手動驗證和拋出的絕佳替代方案。 當輸入類型為output | null | undefined時,OP 中的方法有效output | null | undefined output | null | undefined output | null | undefined或類似的東西,runtypes 也可以在輸入類型為any ,例如在防御性解碼具有已知結構的 JSON 時。

你會像這樣使用它:

import { String } from 'runtypes';
const setting = String.check(process.env.SETTING)

如果process.env.SETTINGundefined它會拋出。 添加.withConstraint()以添加其他條件。 該庫實際上非常強大,不僅可以驗證簡單類型​​,還可以以類型安全的方式驗證記錄(接口)、聯合等。

一個缺點是您無法自定義錯誤消息(“失敗的約束檢查”),這在許多快速而骯臟的情況下是可以的,因為發生錯誤的行會告訴您問題是什么。

io-ts是另一個類似的庫,盡管它似乎有一種更復雜的方法,並且目前還在不斷變化。

throw沒有返回值。 所以你不能那樣使用它。 但是,您可以將 throw 包裝在函數中。 到時候就可以了。 但是找到異常的來源會更困難。

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.

順便說一句,我的經驗告訴我,環境變量的默認值是邪惡的。

雖然不能直接將throw用作表達式,但它可以像Koooilnc建議的那樣在立即調用的匿名閉包中使用,或者像casablanca建議的那樣分離到它自己的語句中,或者像Alex Yarochevich建議的那樣用 Node 的assert替換。

然而,今天執行此操作的最常見和慣用的方法可能是使用tiny-invariant或類似的 function。

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 中的類型適當縮小,可以在瀏覽器中使用。

它也比我之前建議的使用運行時類型庫輕量得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM