我很好奇您是否可以在Express应用中编写if
语句来有条件地执行代码而无需提供else
语句。
if(pred) {
doSomething()
}
return foo;
calcBar(); // doesn't run.
上面是在return
语句之后停止执行的同步代码。
我的Express功能如下:
app.get('/matches', async function(req, res) {
try {
const data = await someGraphQLCall();
if(data.length === 0) {
res.json({ message: "No data." });
}
const someOtherData = await someOtherGraphQLCall(data.foo);
res.json({ someOtherData });
} catch (err) {
res.json({err})
}
}
由于this question,我知道第一个res.json
之后的代码可能仍会执行。有办法阻止这种情况吗?如果第一个条件满足,我不希望第二个GraphQL调用执行。不使用else
可以做到吗?
编辑:
正如我上面链接的问题所述,使用return
语句是一个错误的选择,因为:
它也使它的意义和模糊性降低,因为它使用了不正确的语义。如果您未使用该函数中的值,则不应返回一个。
答案 0 :(得分:3)
您可以在第一个响应上使用return
关键字,以立即从函数返回。
app.get('/matches', async function(req, res) {
try {
const data = await someGraphQLCall();
if(data.length === 0) {
return res.json({ message: "No data." });
}
const someOtherData = await someOtherGraphQLCall(data.foo);
res.json({ someOtherData });
} catch (err) {
res.json({err})
}
}
编辑:
作为替代方案,您可以拆分数据逻辑并建立响应。这样,您可以使用return,并且更易于阅读:
app.get('/matches', async function (req, res) {
try {
const data = await getDataFromGraphQLCall();
res.json(data);
} catch (err) {
res.json({ err })
}
});
async function getDataFromGraphQLCall() {
const data = await someGraphQLCall();
if (data.length === 0) {
return { message: "No data." };
}
const someOtherData = await someOtherGraphQLCall(data.foo);
return { someOtherData };
}
答案 1 :(得分:2)
如果您想知道没有else
的话是否可以实现这一目标,是的。
但是,这可能不是最简单的方法。 IMO,使用return
是停止执行控制器的最佳方法。
无论如何,您可以将代码块拆分为中间件,并使用三元运算符有条件地发送响应。
在您的示例中,按如下所示分隔data = await someGraphQLCall();
:
const middlewareOne = async function(req, res, next) {
let data = [];
let response = { message: "No data." };
try {
data = await someGraphQLCall();
req.locals.data = data; // <- attach the data to req.locals
} catch (err) {
response = { err };
}
data.length === 0 ? res.json(response) : next();
};
然后,将middlewareOne
安装在控制器上:
app.get("/matches", middlewareOne, async function controller(req, res) {
try {
const someOtherData = await someOtherGraphQLCall(req.locals.data.foo);
res.json({ someOtherData });
} catch (err) {
res.json({ err });
}
});
这是如何工作的,如果从先前的中间件(在示例中为controller
)调用next()
,则只能通过express执行middlewareOne
函数。
而且由于middlewareOne
仅在next()
不为0时才调用data.length
,因此它将按预期工作。
有关将数据从一种中间件传递到另一种中间件的更多信息,请阅读this
答案 2 :(得分:0)
return
语句在此上下文中终止函数执行。我认为,应该先处理成功案例,然后再处理错误案例,因为代码将从上至下读取。
在if
语句中,数据可以为undefined
或null
。
您可以在此处了解更多信息:MDN - return
app.get('/matches', async function(req, res) {
try {
const data = await someGraphQLCall();
// alternative, if (data && data[0]) {
if (data && data.length) {
const someOtherData = await someOtherGraphQLCall(data.foo);
return res.json({ someOtherData });
}
return res.json({ message: "No data." });
} catch (err) {
console.log(err); // log error with logger and drain to loggly.
res.json({ err })
}
}
使用Void
运算符:
Void运算符使您可以返回未定义的值,但可以计算给定的表达式。
您可以在此处了解更多信息:MDN - Void
app.get('/matches', async function(req, res) {
try {
const data = await someGraphQLCall();
// alternative, if (data && data[0]) {
if (data && data.length) {
const someOtherData = await someOtherGraphQLCall(data.foo);
return void res.json({ someOtherData });
}
return void res.json({ message: "No data." });
} catch (err) {
console.log(err); // log error with logger and drain to loggly.
res.json({ err })
}
}