Node.js NodeJS RESTful API-如何正确处理“未定义”的请求变量?

Node.js NodeJS RESTful API-如何正确处理“未定义”的请求变量?,node.js,express,request,undefined,req,Node.js,Express,Request,Undefined,Req,我正在使用NodeJS和Express开发一个restfulapi。 我注意到,传入的请求有时缺少一些预期的变量,这会导致程序崩溃,说它无法将变量的值设置为“未定义”的值,因为请求中没有值。 例子: 应用程序需要variableY,但发送的是variableX: formData: { variableX: 'valueX' } 该程序预期接收variableY,代码如下: const checkVariables = Joi.validate({ variableY: req.b

我正在使用NodeJS和Express开发一个restfulapi。 我注意到,传入的请求有时缺少一些预期的变量,这会导致程序崩溃,说它无法将变量的值设置为“未定义”的值,因为请求中没有值。 例子: 应用程序需要variableY,但发送的是variableX:

 formData: { variableX: 'valueX' }
该程序预期接收variableY,代码如下:

const checkVariables = Joi.validate({ 
    variableY: req.body.variableY,
}, schema);
应用程序崩溃,出现以下错误:

TypeError: Cannot read property 'variableY' of undefined
我考虑了几种处理方法,包括在应用程序启动时声明变量,并使用try-catch来使用它们。 另一种方法是使用if-else、if-chaining或case-switch,但正如您所理解的,当然我正在寻找最干净的方法来实现这一点。 有什么想法吗

多谢各位

**编辑** 仅使用对象进行并设法实现结果。尝试访问其任何内部字段后,仍将抛出错误,例如: ifreq.body.variableY==未定义{console.log'预期变量未定义';}//true

当验证处理“未定义”对象内的字段时: ifreq.body.variableY.dataId==未定义{console.log'预期变量未定义';}// 再次抛出以下错误: TypeError:无法读取未定义的属性“variableX”

在进行进一步挖掘后,发现了以下Stackoverflow线程: 尝试使用hasOwnProperty,但引发了相同类型的错误: TypeError:无法读取未定义的属性“hasOwnProperty”

尝试使用try-catch包装变量声明,但仍然无效:

try{
    var variableX = req.body.variableX
    var variableXDataId = req.body.variableX.dataId
}
catch(e){
    res.status(400).send('Wrong request error: Please check your request variables and try again');
}
由于这是一个非常基本的验证,应该由大多数RESTful API来验证您是否在请求中获得了预期的传入变量,因此程序不会因为无法处理错误而崩溃-对于此类问题,预期/意外的请求验证的常见解决方案是什么


谢谢。

您可以采取另一种方法,在到达checkVariables之前检查req.body:

更新

下面是一个关于在/usersStatus/:id请求期间如何工作的示例:

const express=需要“express” const app=express 常数端口=3000 const setKeys=数据,requiredKeys=>{ 如果!所需键的类型。长度{ 所需密钥=[]; } 如果需要KEYS.length requiredKeys.forEachk=>{ k=k.替换/\+/g'/; 让keysList=[]; if/\/+/g.testk{ keysList=k.split'/'; }否则{ keysList=[k]; } 让[firstKey,…rest]=keysList; 如果数据类型[firstKey]=“未定义”{ 数据[firstKey]={}; } 如果静止,那么长度{ data[firstKey]=setKeysdata[firstKey],[rest.join'/']; } } 返回数据; } /** *模拟一些数据 */ const getUserData=req,res,next=>{ 如果type of req.body==“未定义”{ req.body={}; } 请求正文={ 可变的:{ 姓名:23 }, variableZ:{ 姓名:3,, 类型:{ id:5, typeName:'某物', 标签:['a','b','c'] } } }; log'Middleware 1 getUserData'; 下一个 } /** * 1. 设置用于检查密钥的中间件 *requiredKeys是一个字符串数组 */ const middlewareSetKeys=requiredKeys,wrappeddmddleware=>{ 返回请求,res,next=>{ console.log'Middleware 2 middlewareSetKeys'; 如果请求主体的类型===未定义{ log“离开中间件2,因为我们没有req.body”; 下一个 } /** *使用我们希望可用的密钥更新req.body *在我们的下一个中间件中 */ req.body=setKeysreq.body,requiredKeys; 如果WrappedAddressware的类型=='函数'{ 返回wrappedmdleware.callthis、req、res、next; }否则{ 下一个 } } } /** * 2. 让我们假设一个用户状态的情况 * 2.1. 我们需要数据库中的用户信息 * 2.2. 一些信息将不会被检索,除非用户访问网站的某些部分以触发某些机制,允许这些字段被公开,因此缺少密钥 * 2.3. 但是我们知道这些键/对象,我们仍然希望存在,这样我们的代码就不会崩溃。 */ //让我们调用getUserData app.get “/”,//此路径用于某些用户信息 getUserData,//返回userInfo并将其附加到`req.data` 米德尔瓦雷斯钥匙[ 'userActivity/daily/jobs',//这些将不存在于getUserData中,因为该用户是懒惰的,并且他没有申请任何作业 'userStatus/active/two weeks ago',//这些在getUserData中不存在,因为用户两天前加入了。但是我们仍然需要它,因为它是Reazon。 ],//我们将所需的设置为以后使用键 请求,res,next=>{ /** *3.现在我们的请求主体将拥有我们的密钥 *即使它们不存在于getUserData中间件中 */ 控制台,日志 软件3你的中间件'; console.logreq.body; res.setHeader'Content-Type'、'application/json'; res.sendJSON.stringifyreq.body,null,2 }
app.listenport,=>console.log`示例应用程序侦听端口${port}` 您可以使用express验证器 验证传入请求。然后将其添加到控制器中,其中a、b、c、d是您要验证的参数

const nonEmptyFields=['a','b','c','d']; nonEmptyFields.forEachfield=>req.assertfield,`${field}不能为空`.notEmpty; const errors=req.validationErrors; 如果错误{ 返回res.status400.senderrors;
} 解决方案是在父级设置一个默认的空对象来替换未定义的对象:

// checking for body.variableX.variableZ with object destructuring ES6
const {body = {}} = request;
const {variableX = {}, variableY} = body;
const {variableZ} = variableX.variableZ;

// or prior ES6
var body = request.body || {};
var variableX = body.variableX || {};
var variableY = variableX.variableY;

// or in a statement
var variableY = request.body && request.body.variableX ? request.body.variableX.variableY : undefined;
基于此,您可以创建自己的函数,如getValuerequest,“body.variableX.variableY”,以在任何父级或结束值未定义时返回null:

// asumes the value in the path is either object or undefined
function getValue(rootObj, path = '') {
    const parts = key.split('.');
    let value = rootObj || {};
    let part;
    while ((part = parts.shift()) && value !== null) {
        value = value[part] || null;
    }
    return value;
};

它仅适用于“top”对象,一旦尝试验证未定义对象内的字段,将再次引发以下错误:TypeError:在找到此帖子后无法读取未定义的属性“variableY”:[尝试使用hasOwnProperty,但引发了相同类型的错误:TypeError:无论如何都无法读取未定义的属性'hasOwnProperty',以通过该错误?这是验证传入请求的基本方法。我已使用深度对象扫描更新了我的答案。根据您的编辑,您似乎需要已经有一个re的列表quired字段/键并对照该列表检查req.body,您不能只调用任何未定义的键而不进行脚本检查。谢谢linux。字段中的字段如何?例如req.body.variableX.dataId?
// asumes the value in the path is either object or undefined
function getValue(rootObj, path = '') {
    const parts = key.split('.');
    let value = rootObj || {};
    let part;
    while ((part = parts.shift()) && value !== null) {
        value = value[part] || null;
    }
    return value;
};